You can make plots with any tool you like. But we may help you a little with the open source matplotlib library for scientific ploting, which runs with Python.
References:
You need to install Python3.x
Check the existence of Python3 by typing python3 --version
in your terminal (Powershell for Windows). Otherwise, you need to install a python environment in your device:
brew install python
pip install python
You need to install matplotlib & numpy
pip install matplotlib
pip install numpy
Then you should be able import this library.
import matplotlib.pyplot as plt
You need a code editor
We recommend to use JupyterLab, a web-based interactive coding application. You could install it with pip install jupyterlab
and then launch it with jupiter lab
.
Modern IDEs like VsCode are also worth trying.
let's plot a sine function with Matplotlib:
plot()
to draw a line that connects all the points
import numpy as np
import matplotlib.pyplot as plt
x = np.arange(0, 3*np.pi, 0.1) # array for x axis
y = np.sin(x) # array for y axis
plt.plot(x, y) # plot x vs y
plt.savefig('sine.png') # save to file
plt.show() # show on screen
import numpy as np
import matplotlib.pyplot as plt
x = np.arange(0, 3*np.pi, 0.1) # array for x axis
y = np.sin(x) # array for y axis
plt.plot(x, y) # plot x vs y
plt.savefig('sine.png') # save to file
plt.show() # show on screen
import numpy as np
import matplotlib.pyplot as plt
x = np.arange(0, 3*np.pi, 0.1) # array for x axis
y = np.sin(x) # array for y axis
plt.plot(x, y, label = 'sin(x)')
plt.xlabel('physical quantity on x axis (unit)')
plt.ylabel('physical quantity on y axis (unit)')
plt.legend() # create legend
plt.savefig('sine.png') # save to file
plt.show() # show on screen
plt.figure(figsize = (7,5),facecolor= 'yellow') # create a new figure
plt.xlabel('physical quantity on x axis (unit)', fontsize = 12)
plt.ylabel('physical quantity on y axis (unit)', fontsize = 12)
plt.legend(fontsize = 12) # create legend
plt.title('title for this figure',fontsize = 15)
plt.savefig('sine_highQ.png', dpi = 288, bbox_inches = 'tight') # this "tight" command is important
You can use 'color' argument to assign the color of the line.
plt.plot(x, y, color = 'r', label = "color = red")
plt.plot(x, y+1, color = 'k', label = 'color = \'k\'')
You can use 'linestyle' argument to change the look of the line.
linestyle='-'
: (default) solid line
linestyle='--'
: dashed line
linestyle=':'
: dotted line
linestyle=''
: do not plot line
plt.plot(x, y, linestyle='--', label="linestyle='--'")
plt.plot(x, y+1, linestyle=':', label='linestyle=\':\'')
plt.plot(x, y+2, linestyle='', marker='.', label='linestyle=\'\', marker=\'.\'')
You can use 'marker' argument to label the data point on the line.
plt.plot(x, y, color='b', marker='.', label='marker=\'.\'')
plt.plot(x, y+1, color='b', marker='+', label='marker=\'+\'')
plt.plot(x, y+2, color='b', marker='o', label='marker=\'o\'')
plt.plot(x, y, linewidth=4, label='linewidth=4')
plt.plot(x, y+1, 'k', label = 'solid black')
plt.plot(x, y+1, linewidth=10, alpha = 0.5, label='linewidth=10, alpha=0.5')
fig = plt.figure(figsize=(5,4),facecolor= 'white')
ax = fig.add_axes([0,0,1,1])
line, = ax.plot(x,y)
line.set_color('red')
ax.set_xlabel('x')
ax.set_ylabel('y')
ax.set_title('title')
fig.savefig('line_object.png')
note, there is a "," in line, = ax.plot(x,y)
why? ax.plot()
returns a list of line objects.
fig, ax, line are respectively objects of figure, axes and line plots.
add_axes()
, plot()
and set_color()
are respectively
attributes
/ functions of these objects.
🤔why object?
Now you can change attributes of every object on this figure!
💡To modify the attribute, you usually use set_?()
sometimes we want to plot sultiple subfigures in one figure, this is often done by fig.add_subplots()
or plt.subplots()
. Now we create a figure with 2 times 3 panels:
fig, axes = plt.subplots(2, 3) # create subplot
((ax11, ax12, ax13), (ax21, ax22, ax23)) = axes
ax11.plot(x, y) # plot on each axes
ax12.plot(x, y+1)
ax13.plot(x, y+2)
ax21.plot(x, y+3)
ax22.plot(x, y+4)
ax23.plot(x, y+5)
The line fig, axes = plt.subplots(2, 3)
returns a Figure and a 2x3 array of Axes objects
Add argument
sharey=True
to the subplots() so that every subplot share the same y axis property (like range, scale ...)
fig, axes = plt.subplots(2, 3, sharey=True)
((ax11, ax12, ax13), (ax21, ax22, ax23)) = axes
ax11.plot(x, y)
ax12.plot(x, y+1)
ax13.plot(x, y+2)
ax21.plot(x, y+3)
ax22.plot(x, y+4)
ax23.plot(x, y+5)
sharex=True
to share the same x-axis
add argument width_ratios/height_ratios=[the ratio you allocate]
to the subplots() to set the width and height fraction of each subplot.
from matplotlib.gridspec import GridSpec
fig = plt.figure()
gs = GridSpec(2, 3, width_ratios=[1, 2, 3], height_ratios=[2, 1])
axes = [fig.add_subplot(gs[i, j]) for i in range(2) for j in range(3)]
for i, ax in enumerate(axes):
ax.plot(x, [v + i for v in y])
plt.show()
💡 try plt.subplots_adjust(wspace =, hspace=,)
to adjust the space between subplots.
G = gridspec(rows,cols,…)
, ax.inset_axes(extent)
... You can find them on the cheatsheet.
Sometimes we want to plot 2 quantities with the same invariant in one plot, this can be done with ax.twinx()
.
fig, ax = plt.subplots(1,1,figsize=(5,4))
ax.plot(x, y)
ax.set_ylabel('label for left y axis')
ax2 = ax.twinx()
ax2.plot(x, -y, color='r', label='plot on right y axis')
ax2.tick_params(labelcolor='r', axis='y') # red axis label
ax2.set_ylabel('label for right y axis',color='r')
plt.legend()
ax.twiny()
is also available
We could add colorbar in a figure to represent additional information.
radius = 1 # Radius of the circular orbit
num_points = 100 # Number of points to represent the orbit
time = np.linspace(0, 1, num_points) # Time normalized between 0 and 1
x = radius * np.cos(2 * np.pi * time)
y = radius * np.sin(2 * np.pi * time)
fig, ax = plt.subplots()
sc = ax.scatter(x, y, c=time, cmap='viridis', s=50)
ax.plot(x, y, color='gray', linestyle='--', alpha=0.5) # Circular orbit path
cbar = plt.colorbar(sc, ax=ax)
cbar.set_label('Time (normalized)')
ax.set_aspect('equal', adjustable='box') # Equal aspect ratio
ax.set_xlabel('x (AU)')
ax.set_ylabel('y (AU)')
ax.set_title('Circular Orbit with Time Colorbar')
cmap
parameter.
Aspect ratio determines the length ratio of unit y axis and x axis.
plt.plot(xcircle, ycircle)
ax = plt.gca()
ax.set_aspect('equal')
plt.subplots(figsize=(6, 6))
.
sometimes the best scale is not linear
logarithmic axis
ax.set_xscale('log')
ax.set_yscale('log')
ax.annotate()
to put descriptions on the plot.
sometimes you focus on different scales
ax.set_xlim([0, 1])
ax.set_ylim([0, 1])
set_xbound([0, 1])
to achieve similar effect.
You may need this in the homework. You can use readline()
to read in .txt file.
with open('solar_system_planet.txt', 'r') as file:
# Read the first line to get the headers
headers = file.readline().strip().split(',')
data = []
for line in file:
# Read the rest of the lines for data
row_data = line.strip().split(',')
# Append the row data to the data list
data.append(row_data)
print("Headers:", headers)
print("Data:", data)
string.split(',')
string.strip(' ')
readline()
is useful to skip the lines you don't need.
pandas
read in data as python dictionary. import pandas as pd
import matplotlib.pyplot as plt
data = pd.read_csv('solar_system_planet.txt',delimiter=',')
radius = data['radius']
mass = data['mass']
text = data['object']
fig, ax = plt.subplots(1,1,figsize=(6,4))
ax.scatter(radius,mass,color='tab:blue',s=100,alpha= 0.5)
ax.set_xlabel(r'radius ($R_\oplus$)')
ax.set_ylabel(r'mass ($M_\oplus$)')
for i in range(len(text)):
if (text[i] == 'Venus') or (text[i] == 'Uranus'):
ax.annotate(text[i], (radius[i], mass[i]), textcoords="offset points", xytext=(0,-12), ha='center')
else:
ax.annotate(text[i], (radius[i], mass[i]), textcoords="offset points", xytext=(0,12), ha='center')
ax.set_yscale('log')
ax.set_xscale('log')
plt.show()