102 lines
2.5 KiB
Python

# %%
# Import required libraries
import numpy as np # Numerical operations and array handling
import matplotlib.pyplot as plt # Plotting library
# Global plotting parameters
fig = 0
lw = 3
x_0 = -8.0
x_E = 8.0
N = 257
# Named color palette mapping descriptive names to hex codes
colors = {
"deep blue": "#1f77b4",
"orange": "#ff7f0e",
"green": "#2ca02c",
"red": "#d62728",
}
# Each entry describes one figure: a list of curves to overlay,
# plus the y-axis limits for readability
figures = [
{
"curves": [
{
"f": lambda x: np.sinh(x),
"label": r"$f(x) = \sinh(x)$",
"color": colors["deep blue"],
},
{
"f": lambda x: np.cosh(x),
"label": r"$f(x) = \cosh(x)$",
"color": colors["orange"],
},
],
"y_lim": (-3, 6),
},
{
"curves": [
{
"f": lambda x: np.tanh(x),
"label": r"$f(x) = \tanh(x)$",
"color": colors["red"],
},
{
"f": lambda x: 1 / np.tanh(x),
"label": r"$f(x) = \coth(x)$",
"color": colors["green"],
},
],
"y_lim": (-4, 4),
},
]
# Generate the shared x-axis data once
x_data = np.linspace(x_0, x_E, N)
# Loop over each figure definition
for figure in figures:
# Create a new figure
fh = plt.figure(fig)
fig += 1
# Retrieve the y-limits for this figure
y_lim = figure["y_lim"]
# Plot each curve in the current figure
for curve in figure["curves"]:
# Evaluate the function over the shared x-range
y_data = curve["f"](x_data)
# Mask values outside the visible y-range with NaN.
# This both hides non-finite values (inf/nan from division by
# zero) and breaks the line at vertical asymptotes, so matplotlib
# never connects a point from one branch to the next.
y_data = np.where((y_data > y_lim[0]) & (y_data < y_lim[1]), y_data, np.nan)
plt.plot(
x_data,
y_data,
linewidth=lw,
color=curve["color"],
label=curve["label"],
)
# Set axis labels
plt.xlabel(r"$x$")
plt.ylabel(r"$y$")
# Display a grid for readability
plt.grid(visible=True)
# Set y-limits to keep all curves visible
plt.ylim(y_lim)
# Add a legend showing the function expression in LaTeX
plt.legend()
# Display all figures
plt.show()