# 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. ``````# 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-r, p-r, p+r, p+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**2+vec**2)
def vecmul(vec, n):
return (vec*n, vec*n)
def vecnorm(vec):
return vecmul(vec, 1./veclen(vec))
return (vec1+vec2, vec1+vec2)
def newvector(p1, p2):
return (p1-p2, p1-p2)

# get the point on a circle
def circlepos(p, r, phi):
return (p+r*math.cos(phi), p+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)
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*_)
phi = veclen(v)/phifactor+getphishift(y)
cv = circlepos((0, 0), arrowlen, phi)

# circle vector at the destination
cv1 = circlepos((0, 0), arrowlen, veclen(vec1)/phifactor)
cv2 = circlepos((0, 0), arrowlen, veclen(vec2)/phifactor)
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))
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()``````

This site uses Akismet to reduce spam. Learn how your comment data is processed.