#!/usr/bin/python # -*- coding: utf8 -*- from math import * import matplotlib.pyplot as plt from matplotlib import animation, colors, colorbar import numpy as np import colorsys from scipy.interpolate import interp1d import os, sys plt.rc('path', snap=False) plt.rc('mathtext', default='regular') # image settings fname = 'QHO-coherentstate3-animation-color' width, height = 300, 200 ml, mr, mt, mb, mh, mc = 35, 19, 22, 45, 12, 6 x0, x1 = -7, 7 y0, y1 = 0.0, 0.7 nframes = 150 fps = 20 # physics settings alpha0 = 3.0 omega = 2*pi def color(phase): hue = (phase / (2*pi) + 2./3.) % 1 light = interp1d([0, 1, 2, 3, 4, 5, 6], # adjust lightness [0.64, 0.5, 0.55, 0.48, 0.70, 0.57, 0.64])(6 * hue) hls = (hue, light, 1.0) # maximum saturation rgb = colorsys.hls_to_rgb(*hls) return rgb def coherent(alpha0, x, omega_t): # Definition of coherent states # https://en.wikipedia.org/wiki/Coherent_states alpha = alpha0 * e**(-1j * omega_t) psi = pi**-0.25 * np.exp(-0.5j * omega_t - 0.5 * ((x - sqrt(2) * alpha.real))**2 - 1j * alpha.imag * (alpha.real - sqrt(2) * x)) return psi def animate(nframe): print str(nframe) + ' ',; sys.stdout.flush() t = float(nframe) / nframes # animation repeats after t=1.0 ax.cla() ax.grid(True) ax.axis((x0, x1, y0, y1)) x = np.linspace(x0, x1, int(ceil(1+w_px))) x2 = x - px_w/2. # Let's cheat a bit: add a phase phi(t)*const(x) # This will reduce the period from T=2*(2pi/omega) to T=1.0*(2pi/omega) # and allow fewer frames and less file size for repetition. # For big alpha the change is hardly visible psi = coherent(alpha0, x, omega * t) * np.exp(-0.5j * omega * t) psi2 = coherent(alpha0, x2, omega * t) * np.exp(-0.5j * omega * t) y = np.abs(psi)**2 phi = np.angle(psi2) # plot color filling for x_, phi_, y_ in zip(x, phi, y): ax.plot([x_, x_], [0, y_], color=color(phi_), lw=2*0.72) ax.plot(x, y, lw=2, color='black') ax.set_yticklabels([l for l in ax.get_yticks() if l < y0+0.9*(y1-y0)]) # create figure and axes plt.close('all') fig, ax = plt.subplots(1, figsize=(width/100., height/100.)) bounds = [float(ml)/width, float(mb)/height, 1.0 - float(mr+mc+mh)/width, 1.0 - float(mt)/height] fig.subplots_adjust(left=bounds[0], bottom=bounds[1], right=bounds[2], top=bounds[3], hspace=0) w_px = width - (ml+mr+mh+mc) # plot width in pixels px_w = float(x1 - x0) / w_px # width of one pixel in plot units # axes labels fig.text(0.5 + 0.5 * float(ml-mh-mc-mr)/width, 4./height, r'$x\ \ [(\hbar/(m\omega))^{1/2}]$', ha='center') fig.text(5./width, 1.0, '$|\psi|^2$', va='top') # colorbar for phase cax = fig.add_axes([1.0 - float(mr+mc)/width, float(mb)/height, float(mc)/width, 1.0 - float(mb+mt)/height]) cax.yaxis.set_tick_params(length=2) cmap = colors.ListedColormap([color(phase) for phase in np.linspace(0, 2*pi, 384, endpoint=False)]) norm = colors.Normalize(0, 2*pi) cbar = colorbar.ColorbarBase(cax, cmap=cmap, norm=norm, orientation='vertical', ticks=np.linspace(0, 2*pi, 3)) cax.set_yticklabels(['$0$', r'$\pi$', r'$2\pi$'], rotation=90) fig.text(1.0 - 10./width, 1.0, '$arg(\psi)$', ha='right', va='top') plt.sca(ax) # start animation if 0 != os.system('convert -version > ' + os.devnull): print 'imagemagick not installed!' # warning: imagemagick produces somewhat jagged and therefore large gifs anim = animation.FuncAnimation(fig, animate, frames=nframes) anim.save(fname + '.gif', writer='imagemagick', fps=fps) else: # unfortunately the matplotlib imagemagick backend does not support # options which are necessary to generate high quality output without # framewise color palettes. Therefore save all frames and convert then. if not os.path.isdir(fname): os.mkdir(fname) fnames = [] for frame in range(nframes): animate(frame) imgname = os.path.join(fname, fname + '{:03d}'.format(frame) + '.png') fig.savefig(imgname) fnames.append(imgname) # compile optimized animation with ImageMagick cmd = 'convert -loop 0 -delay ' + str(100 / fps) + ' ' cmd += ' '.join(fnames) # now create optimized palette from all frames cmd += r' \( -clone 0--1 \( -clone 0--1 -fill black -colorize 100% \) ' cmd += '-append +dither -colors 255 -unique-colors ' cmd += '-write mpr:colormap +delete \) +dither -map mpr:colormap ' cmd += '-alpha activate -layers OptimizeTransparency ' cmd += fname + '.gif' os.system(cmd) for fnamei in fnames: os.remove(fnamei) os.rmdir(fname)