In [1]:
import numpy as np
import matplotlib.pyplot as plt
from matplotlib import animation
from matplotlib import rc
import ipywidgets as ipw

from ipywidgets import interact,interactive
import ipywidgets as widgets

from IPython.display import HTML
rc('text', usetex=True)

%matplotlib widget

global global_K1
global global_K2
global global_branche
global global_selected_k
In [2]:
def get_closest_point(clic_x,clic_y):
    # Get the data from the figure
    ax= plt.gca() # get axis handle
    acoustic_data = ax.lines[1]
    optic_data = ax.lines[0]

    # Find which line was closer
    #closet x data
    k_a = acoustic_data.get_xdata()
    k_o = optic_data.get_xdata()
    diff_k_a = np.abs(k_a-clic_x)
    diff_k_o = np.abs(k_o-clic_x)
    # get the x index corresponding to the closet k in the graph for both branches
    index_a = np.argmin(diff_k_a)
    index_o = np.argmin(diff_k_o)

    # compute the distance on the y axis
    y_diff_a = np.abs(acoustic_data.get_ydata()[index_a]-clic_y)
    y_diff_o = np.abs(optic_data.get_ydata()[index_o]-clic_y)

    ac_is_closer = y_diff_a < y_diff_o
    # print a x at the postion 
    global global_branche
    global global_selected_k
    global global_omega
    
    if(ac_is_closer):
        global_branche=1
        global_selected_k = acoustic_data.get_xdata()[index_a]
        global_omega = acoustic_data.get_ydata()[index_a]
        return [acoustic_data.get_xdata()[index_a], acoustic_data.get_ydata()[index_a]]
    else:
        global_branche=2
        global_selected_k = optic_data.get_xdata()[index_a]
        global_omega = optic_data.get_ydata()[index_a]

        return [optic_data.get_xdata()[index_a], optic_data.get_ydata()[index_a]]
In [3]:
def interactive_lattice_plot(G,K):
    '''
    :param G,K: coupling
    plot acoustic and optical phonons bands
    '''
    
    # save the current values of G and K    
    global global_K1
    global global_K2
    global_K1=G
    global_K2=K
    
    k = np.linspace(-np.pi/2,np.pi/2,100)
    
    omega_o = G+K-np.sqrt((G+K)**2-4*G*K*np.sin(k)**2)
    omega_a = G+K+np.sqrt((G+K)**2-4*G*K*np.sin(k)**2)
    
#     print(omega_o, omega_a)
    ax1.clear();
    ax1.plot(k,np.sqrt(omega_a))
    ax1.plot(k,np.sqrt(omega_o))
    ax1.set_xlabel("k")
    ax1.set_ylabel("$\omega$")
    ax1.set_xticks(np.linspace(-np.pi/2,np.pi/2,5))
    ax1.set_xticklabels(['$-\pi/a$','','0','','$\pi/a$'])
       
    def onclick(event):    
        # clear the previous point 
        for i in np.arange(3, len(ax1.lines)+1) :
            ax1.lines.pop()
        # Get the coordonate of the data closest from the click
        [x,y]=get_closest_point(event.xdata,event.ydata)
        ax1.plot(x, y, '.',color='red')
    
    cid = fig.canvas.mpl_connect('button_press_event', onclick)
    plt.show()
In [4]:
g = ipw.FloatSlider(min=1, max=6, step=0.05, value=6);
k = ipw.FloatSlider(min=1, max=6, step=0.05, value=1);
fig=plt.figure()
ax1=plt.axes()
plt.ion()
interactive(interactive_lattice_plot, G=g, K=k)
Canvas(toolbar=Toolbar(toolitems=[('Home', 'Reset original view', 'home', 'home'), ('Back', 'Back to previous …
interactive(children=(FloatSlider(value=6.0, description='G', max=6.0, min=1.0, step=0.05), FloatSlider(value=…
In [ ]:
fig2 = plt.figure()
ax2 = plt.axes()
ax2.set_xlim([-2,10])
ax2.set_xticks([])
ax2.set_yticks([])
line_u, = ax2.plot([], [], "ok")
line_v, = ax2.plot([], [], "ob")
if global_branche == 1:
    ax2.title.set_text("Acoustic")
else : 
    ax2.title.set_text("Optic")

a = 2 # lattice parameter
d = 0.5 # distance between atoms 1 and 2 in basis 
N=5 # number of repeated basis
pos_u = np.arange(N)*a 
pos_v = np.arange(N)*a+d
ax2.plot(pos_u,np.zeros(N),"ok",mfc='none')
ax2.plot(pos_v,np.zeros(N),"ob",mfc='none')
# Initialization function: plot the background of each frame
def init():
    line_u.set_data([], [])
    line_v.set_data([], [])

    return line_u,

# Animation function which updates figure data.  This is called sequentially
def animate(iteration):
    t=0.05*iteration
    a = 2 # lattice parameter
    d = 0.5 # distance between atoms 1 and 2 in basis 
    N=5 # number of repeated basis 
    global global_branche # acoustic or optical selected in the previous graph
    global global_selected_k # wave number selected in the previous graph
    relative_phase = (-1)** (1+global_branche) # relative phase between atom 1 and 2 in the basis

    global global_K1
    global global_K2 # interactions 
    
    a_nu = d/3.45*(relative_phase*(global_K1+global_K2*np.exp(1j*global_selected_k*a))/np.abs(global_K1+global_K2*np.exp(1j*global_selected_k*a)))
    b_nu = d/3.45 
    
    ns = np.arange(N)
    u_n = np.real(a_nu*np.exp(1j*global_selected_k*ns*a-1j*global_omega*t))
    v_n = np.real(b_nu*np.exp(1j*global_selected_k*ns*a-1j*global_omega*t))
    
    pos_u = np.arange(N)*a + u_n
    pos_v = np.arange(N)*a+d+v_n
    
    line_u.set_data(np.asarray([pos_u,np.zeros(N)]))
    line_v.set_data(np.asarray([pos_v,np.zeros(N)]))
    return line_u,
In [ ]:
# Call the animator
anim = animation.FuncAnimation(fig2, animate, init_func=init, frames=300, interval=30, blit=True)
In [ ]:
 
In [ ]:
 
In [ ]:
 
In [ ]:
 
In [ ]: