# slope_field_r1.py

Created by john-c-2021

Created on January 17, 2021

6.19 KB

An updated (Rev 1) of slope_field.py to add a few user selected diffyQs. Note: selecting the max number of points (axes -4 to +4 = 81 points seems to run the Numworks calculator “out of memory” when the diffyQ is: dy/dx = sin(x)/y. No error is thrown but the display is blank. YMMV.

```from matplotlib.pyplot import *
from math import *

# The user will input a minimum value for the x axis.
# The user input should be an integer between -4 and -2
# The x and y axes will be set equal to each other at +- this value
# Note: at -4 a 9 point x 9 point slope field is produced.
# Currently, any slope field wih > 81 (9x9) points = out of memory.
# The user will also choose from a selection of predetmined functions
# to use for the display of the slope field,
# By John Cantlin 1-16-2021 with help from Logan Burch.

# obtain and validate user input for the axes
def valid_axis(_a):
if(-4 <= _a <= -2) and (isinstance(_a,int)):
return "Good"
else:
print("x axis min: int -4 to -2")
return False

x_axis_good = False
x_axis_min = int(input("Enter x axis min -4 to -2: "))
x_axis_good = valid_axis(x_axis_min)

while not x_axis_good:
x_axis_min = int(input("Enter x axis min  -4 to -2: "))
x_axis_good = valid_axis(x_axis_min)

# set the x-y axes min/max to equal (symmetric) +- values
y_axis_min = x_axis_min
x_axis_max = abs(x_axis_min)
y_axis_max = abs(x_axis_min)
print("x-axis: ", x_axis_min, " to ", x_axis_max)
print("y-axis: ", y_axis_min, " to ", y_axis_max)

# create a list of x and corresponding y lattice point coordinates usingaxes max/min
x = list(range(x_axis_min, x_axis_max + 1, 1))  # range(start, stop. step)
y = list(range(x_axis_min, x_axis_max + 1, 1))  # range(start, stop. step)
print("x: ", x)
print("y: ", y)
wait = input("Press Enter to continue.")

# obtain and validate the user selection for the function to display
print("Enter function number:")
print("1: dy/dx=x+y")
print("2: dy/dx=x-y")
print("3: dy/dx=xy")
print("4: dy/dx=x/y")
print("5: dy/dx=sin(x)/y")

# use text labels to echo selection to user and for graph label
# put a dummy string in position 0 so list indices match item selected
dydxstr = ["dummystr", "dy/dx=x+y", "dy/dx=x-y",  "dy/dx=xy", "dy/dx=x/y", "dy/dx=sin(x)/y"]

def valid_selection(_s):
if(1 <= _s <= 5) and (isinstance(_s,int)):
return "Good"
else:
print("Enter int 1 to 4.")
return False

fselect_good = False
fselect = int(input("Enter function number: "))
fselect_good = valid_selection(fselect)

while not fselect_good:
fselect = int(input("Enter function number: "))
fselect_good = valid_selection(fselect)

print("Plot ", fselect, ": ", dydxstr[fselect])

# define the selected derivative function of y in terms of x and y
# that is used for the slope field, include the label used for the graph
if (fselect == 1):
def dydx(_x,_y):    # define the derivative as a function of x and y
m = _x + _y   # find slope m for given x and y, do not divide by zero
return m
elif (fselect == 2):
def dydx(_x,_y):    # define the derivative as a function of x and y
m = _x - _y       # find slope m for given x and y, do not divide by zero
return m
elif (fselect == 3):
def dydx(_x,_y):    # define the derivative as a function of x and y
m = _x * _y       # find slope m for given x and y, do not divide by zero
return m
elif (fselect == 4):
def dydx(_x,_y):       # define the derivative as a function of x and y
try:
m = _x / _y   # define the derivative as a function of x and y
return m
except ZeroDivisionError:
if(_x == 0 and _y == 0):
m = 0
return m
else:
m = 1000    # cheating a little here since m is actually undefined
return m
elif (fselect == 5):
def dydx(_x,_y):       # define the derivative as a function of x and y
try:
m = sin(_x) / _y   # define the derivative as a function of x and y
return m
except ZeroDivisionError:
if(_x == 0 and _y == 0):
m = 1
return m
else:
m = 0
return m
else:
pass

# create list of x, y pairs Note: x and y lists are equal length
x_y = [] # initialize empty list of x, y pairs
xm = []  # initialize empty list of x midpoint values
ym = []  # initialize empty list of y midpoint values

# create nested list of lists of all ordered pairs then extract xm and ym lists
for i in range(len(x)):
for j in range(len(y)):
x_y.append((x[i], y[j]))

for i in range(len(x_y)):
xm.append(x_y[i][0]) # select all x midpoint values

for i in range(len(x_y)):
ym.append(x_y[i][1]) # select all y midpoint values

wait = input("Press Enter to continue.")

# create x and y axes, extend by 1 in each direction so the slope lines are visible
axis((x_axis_min-1,x_axis_max+1,y_axis_min-1,y_axis_max+1))   # axis(Xmin,Xmax,Ymin,Ymax)
axis("on")                  # mathplotlib: turn axes "on"
grid(False)                 # mathplotlib: turn grid "off"

# mathplotlib: draw arrows(x,y,dx,dy) where (x,y) start and (x + dx, y + dy) is end
# i.e. arrows(xs=xm-dx, ys=ym-dy, 2dx, 2dy)
# where length of arrow is set to 2d where d is set to 1/8 = 0.125
# and dx = 2d/root(1+m^2), dy = m*dx
d  = 0.250 # initial value of half the length of each line segment
xs = []    # initialize empty list of xm starting x coordinate for arrows
ys = []    # initialize empty list of xm starting y coordinate for arrows
m  = []    # initialize empty list of m at each value of xm
dx = []    # initialize empty list of dx at each value of xm
dy = []    # initialize empty list of dy at each value of xm

for i in range(len(xm)):
m.append(dydx(xm[i],ym[i]))  # call dydx to calculate m for each (xm,ym) ordered pair
for i in range(len(xm)):         # calculate dx for each for each (xm,ym) ordered pair
dx.append((d)/(sqrt(1 + pow(m[i],2)))) # calculate dx for each xs
for i in range(len(xm)):         #  calculate dy  for each (xm,ym) ordered pair
dy.append(m[i] * dx[i])      # calculate dy for each xs
for i in range(len(xm)):
xs.append(xm[i] - dx[i])     # xs = starting x values of arrows
ys.append(ym[i] - dy[i])     # ys = starting y values of arrows

print("length of lines: ", 2*d)
print("slope m at each (xm,ym): ", m)
wait = input("Press Enter to continue.")

# draw arrows starting at each (xs,ys) ordered pair and moving by 2dx and 2dy
for i in range(len(xs)):