Introduction to Function Plotting


Let's plot some PHYS 20700 level kinematics, namely the speed and position of an object in free fall near the surface of the Earth.

Our first step is to import two libraries that will be useful: numpy, to handle variables in array formats and mapplotlib to the plotting.

import numpy as np
import matplotlib.pyplot as plt

Our setup involves one constant value: the acceleration due to gravity, g. Let's define that as a variable.

# Define a variable to store the value of little g
g = 9.80

Now, we create a list (or array) of time values. The function np.linespace() creates a linear spacing of values set by the 3 arguments in the parenthesis: begin, end, and how many. If you didn't know how the function works, you can always look it up in the documentation: Numpy Linspace

# make a list called time that ranges from 0 to 10 seconds. 
time = np.linspace(0, 10, 100)

Next, we use our physics understanding to make a function for speed v, as a function of time. The following line will create a new list `speed` that is populated by the basic kinematic function that related speed, acceleration, and time. (We'll keep things simple right now, and just say the down is positive y, basically treating everything as scalar quantities and not vectors in a normal xyz coordinate frame) v=v0+at

# make a new list called speed
speed = g*time

Now, we can plot speed as a function of time using our two lists of values that we just created. Make sure to label the axes (and include the units), and give the plot a title.

fig, ax = plt.subplots()

ax.plot(time, speed)
ax.set_xlabel('Time [s]')
ax.set_ylabel('Speed [m/s]')
ax.set_title('Speed as a function of time')

plt.show()

This will result in the following plot

We can also consider the position of the object. That will be given by: x=x0+v0t+12at2 (We can assume for simplicity that x0 and v0 are both zero.)

# create the position list based on the equation above
# we can use the np.square() function to ask for the square of each value in the time list
# rather than the square of the 1-d matrix.
  
position = 0.5*g*np.square(time)

Do the same plot routine, but change the speed to position.

fig, ax = plt.subplots()

ax.plot(time, position, linewidth=2.0)
ax.set_xlabel('Time [s]')
ax.set_ylabel('Position [m]')
ax.set_title('Position as a function of time')

plt.show()

We can annotate plots too, to help explain things. Here's an example where the point halfway through the motion is highlighted.

# Since our lists where 100 values long, we can just call our special point = 50. 

specialPoint = 50

fig, ax = plt.subplots()

ax.plot(time, position, linewidth=2.0)
ax.set_xlabel('Time [s]')
ax.set_ylabel('Position [m]')
ax.set_title('Position as a function of time')
ax.grid()
# This line adds a circular 'o' marker at the specialPoint values for time and position. 
ax.plot(time[specialPoint], position[specialPoint],'o', color = 'tab:blue')

# All of this is for the annotation. 

plt.annotate("Important Data \n Point", # this is the text
                  xy=(time[50], position[50]), # these are the coordinates to position the label
                  textcoords="offset points", # how to position the text
                  xytext=(-40,40), # distance from text to points (x,y)
                  ha='center',
                  va='bottom',
                  bbox=dict(boxstyle='round,pad=0.5', fc='white', alpha=0.2),
                  arrowprops=dict(arrowstyle = '-|>', connectionstyle='arc3, rad=0')) 

plt.show()

Now, let's plot both functions on the same graph. One will use the right axis, the other the left.

fig, ax1 = plt.subplots()

color = 'darkred'
ax1.set_xlabel('time [s]')
ax1.set_ylabel('Speed [m/s]', color=color)
ax1.plot(time, speed, color=color)
ax1.tick_params(axis='y', labelcolor=color)
ax1.set_title('Position and Speed as a function of time')

ax2 = ax1.twinx()  # instantiate a second axes that shares the same x-axis

color = 'darkblue'
ax2.set_ylabel('Position [m]', color=color)  # we already handled the x-label with ax1
ax2.plot(time, position, color=color)
ax2.tick_params(axis='y', labelcolor=color)

fig.tight_layout()  # otherwise the right y-label is slightly clipped
plt.show()

Or perhaps, it's better to separate the plots into different subplots. This example shows all the kinematic terms, a, v, and x separated into three subplots. Note how we made a new list called `acceleration` by filling a numpy array with the constant value g. The great thing about doing plots programaticcaly, rather than in excel, is that if we wanted to redo all this for free fall on the moon for example, where g is 1.6 m/s2, we could just redifine that variable in the beginning, and run the whole notebook, and everything would be updated for that change.
acceleration = np.full((100, 1),g)

fig, axs = plt.subplots(3, 1, figsize=(7, 7))
axs[0].plot(time, acceleration, color = "purple")
axs[0].set_ylabel('acceleration [m/s/s]')
axs[0].grid(True)
axs[0].set_title('The 3 kinematic variables')

axs[1].plot(time, speed, color = "green" )
axs[1].set_ylabel('speed [m/s]')
axs[1].grid(True)

axs[2].plot(time, position, color = "darkblue")
axs[2].set_xlabel('time [s]')
axs[2].set_ylabel('position [m]')
axs[2].grid(True)

fig.tight_layout()
plt.show()


Great. This should be a useful starting point for plotting analytic functions. To test your understanding and further develop this skillset, try making the following modifications.


This tutorial also exists as a Colab Notebook. You can find it here: Colab Function Plotting