Double-Slit Experiment

Light is a fascinating thing in our universe. We perceive it as color, warmth and vision. Yet it does things one may not expect it to do. One of the experiments that called for a better physical model of light was the double slit experiment. In this experiment, a laser is shone through two closely adjacent slits and projected on the screen behind. Using old physical models, one would expect to see one or maybe two specs of light on the screen, when in reality there appear alternating dark and bright spots.

To explain why this seemingly strange phenomenon is occurring, one can either see light as photons and comprehend that a photon presumably follows every possible path there is in the entire universe and then — through it being observed — randomly chooses one path and thus creates stripes (according to the theory of quantum mechanics) or one can see light as simply being a wave.

For more information on the double-slit experiment, I refer to this Wikipedia entry.

The animation shown below describes light as a wave. The green vectors represent the light wave’s phase at the points on the light beam, the yellow vector represents the addition of both of the slit’s light beam’s phase when hitting the screen and the red dots at the screen represent the light’s brightness at that point (defined by the yellow vector’s length).
To create the animation, Python and a Python module called PIL were used to create single frames which were then stitched together by ImageMagick to create an animated gif.

Double-Slit Simulation (probably loading...)


# Jonathan Frech, 18th of January 2017
#          edited 19th of January 2017
#          edited 22nd of January 2017
#          edited 27th of January 2017

# import
from PIL import Image, ImageDraw
import sys, copy, os, math

""" INIT """
# frame steps
steps = 5

# image size
w, h = 1080, 720
size = (w, h)

# both slits
pos1 = (50, h/2-200)
pos2 = (50, h/2+200)

# length of arrows (green lines)
arrowlen = 40

# how does the wave length relate to the beam
wavesteps = .01

# how fast phi changes (smaller is faster)
phifactor = 10.

# how fast the arrows spin (bigger is faster, just for visual show)
wavevisualspeed = 0

# how many points on the beam should be skipped whilst drawing
drawskip = 100

# range in which the destination moves
yrange = range(0, h+1, steps)

# all light points
light = []

# directory for saving the frames
path = os.path.abspath(os.path.dirname(__file__)) + "/p/"

""" FUNCTIONS """
# draw functions
def circle(draw, p, r, fill):
	draw.ellipse((p[0]-r, p[1]-r, p[0]+r, p[1]+r), fill = fill)
def line(draw, p1, p2, fill, width = 1):
	draw.line(p1+p2, fill = fill, width = width)

# vector functions
def veclen(vec):
	return math.sqrt(vec[0]**2+vec[1]**2)
def vecmul(vec, n):
	return (vec[0]*n, vec[1]*n)
def vecnorm(vec):
	return vecmul(vec, 1./veclen(vec))
def vecadd(vec1, vec2):
	return (vec1[0]+vec2[0], vec1[1]+vec2[1])
def newvector(p1, p2):
	return (p1[0]-p2[0], p1[1]-p2[1])

# get the point on a circle
def circlepos(p, r, phi):
	return (p[0]+r*math.cos(phi), p[1]+r*math.sin(phi))

# fill an int with zeros
def fill(n, l):
	return ("0"*(l-len(str(n))))+str(n)

# get beam's destination
def getdest(y):
	return (w-100, y)

# get phi shift (only for show, makes the green arrows turn)
def getphishift(y):
	return y*2*math.pi/h*wavevisualspeed

""" FRAME """
# draw a frame
def frame(y, filename):
	# determine destination point (moves up and down)
	dest = getdest(y)
	
	# colors
	white = (255, 255, 255)
	yellow = (255, 255, 0)
	green = (0, 150, 0)
	
	# save the image, using pillow (PIL)
	img = Image.new("RGB", size)
	pix = img.load()
	draw = ImageDraw.Draw(img)
	
	# draw points
	circle(draw, pos1, 5, white)
	circle(draw, pos2, 5, white)
	circle(draw, dest, 5, white)
	
	# center line
	line(draw, (0, h/2), (w, h/2), (50, 50, 50))
	
	# draw beam
	line(draw, pos1, dest, white)
	line(draw, pos2, dest, white)
	
	# calculate vectors between p and dest
	vec1 = newvector(dest, pos1)
	vec2 = newvector(dest, pos2)	
	
	# draw both beams
	for vec, pos in ((vec1, pos1), (vec2, pos2)):
		# number of vectors drawn
		n = int(veclen(vec)/wavesteps)
		
		# draw vectors
		for _ in range(n+1):
			if _ % drawskip == 0:
				v = vecmul(vec, 1./veclen(vec)*wavesteps*_)
				p = vecadd(pos, v)
				phi = veclen(v)/phifactor+getphishift(y)
				cv = circlepos((0, 0), arrowlen, phi)
				line(draw, p, vecadd(p, cv), green)
	
	# circle vector at the destination
	cv1 = circlepos((0, 0), arrowlen, veclen(vec1)/phifactor)
	cv2 = circlepos((0, 0), arrowlen, veclen(vec2)/phifactor)
	cv = vecadd(cv1, cv2)
	line(draw, dest, vecadd(dest, cv), yellow, 3)
	
	# new light point, draw all light points
	light.append((dest, int(255./maxcvlength*veclen(cv))))
	for p, c in light:
		circle(draw, p, 3, (c, 0, 0))
	
	# save image
	try:
		img.save(path + "%s.png" % filename, "PNG")
	except:
		pass

""" MAIN """
# main
def main():
	global maxcvlength
	
	# determine maximum end vector length (to calculate color)
	maxcvlength = 0
	for y in yrange:
		dest = getdest(y)
		vec1 = newvector(dest, pos1)
		vec2 = newvector(dest, pos2)
		cv1 = circlepos((0, 0), arrowlen, veclen(vec1)/phifactor+getphishift(y))
		cv2 = circlepos((0, 0), arrowlen, veclen(vec2)/phifactor+getphishift(y))
		cv = vecadd(cv1, cv2)
		cvlength = veclen(cv)
		maxcvlength = max(maxcvlength, cvlength)

	# create directory if it does not already exists, if it does, delete it and create a new one
	try:
		if not os.path.exists(path):
			print "Creating directory '%s'..." % path
			os.mkdir(path)
		else:
			print "Cleaning up directory '%s'..." % path
			i = 0
			for _ in os.listdir(path):
				if os.path.isfile(path+_):
					os.remove(path+_)
					i += 1
			print "Removed %d file%s." % (i, ["s", ""][i==1])
	except:
		print "Failed to sort out directors '%s'." % path
	
	# calculate all frames
	print "Calculating frames..."
	i = 0
	for y in yrange:
		frame(y, fill(i, 3))
		i += 1
	for y in yrange[::-1]:
		frame(y, fill(i, 3))
		i += 1
	
	# stitch frames to one animated gif
	try:
		print "Creating gif..."
		os.system("convert -delay 1 p/*.png p/out.gif")
	except:
		print "Failed to create gif."

# run
main()
Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s