For conversion three different plotting scripts building each one it's own surface into a multi-threaded (multi-process) version, we separate the code logic for each surface into a separate task. This allows CPU to calculate simultaneously the paraboloid, sine wave, and Möbius strip.
To setup python3.14.3t on Arch Linux/CachyOS along with aqtinstall via UV
$ curl -LsSf https://astral.sh/uv/install.sh | sh
$ uv python install 3.14t
$ uv python list
$ mkdir MULTITHREAD
$ cd MULTITHREAD
$ python3.14t -m venv .env
$ source .env/bin/activate
$ pip install aqtinstall
$ pip install --upgrade pip
$ pip install numpy matplotlib cxroots
❯ cat plotMulti3Dpython12.py
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.tri import Triangulation
from concurrent.futures import ProcessPoolExecutor
# --- Worker Functions for Parallel Execution ---
def calc_paraboloid():
X = np.linspace(-5, 5, 100)
Y = np.linspace(-5, 5, 100)
X_grid, Y_grid = np.meshgrid(X, Y)
Z = X_grid**2 + Y_grid**2
return X_grid, Y_grid, Z
def calc_sine_tri():
x = np.linspace(-5, 5, 50)
y = np.linspace(-5, 5, 50)
X, Y = np.meshgrid(x, y)
Z = np.sin(np.sqrt(X**2 + Y**2))
triang = Triangulation(X.flatten(), Y.flatten())
return triang, Z.flatten()
def calc_mobius():
theta = np.linspace(0, 2*np.pi, 100)
w = np.linspace(-0.5, 0.5, 10)
theta_grid, w_grid = np.meshgrid(theta, w)
r = 1 + w_grid * np.cos(theta_grid / 2)
x = r * np.cos(theta_grid)
y = r * np.sin(theta_grid)
z = w_grid * np.sin(theta_grid / 2)
return x, y, z
if __name__ == "__main__":
# 1. Execute all three calculations in parallel
with ProcessPoolExecutor() as executor:
f1 = executor.submit(calc_paraboloid)
f2 = executor.submit(calc_sine_tri)
f3 = executor.submit(calc_mobius)
# Gather results as they finish
para_data = f1.result()
sine_data = f2.result()
mobi_data = f3.result()
# 2. Plotting (Main Thread)
# Plot 1: Paraboloid
fig1 = plt.figure()
ax1 = fig1.add_subplot(111, projection='3d')
ax1.plot_surface(*para_data, cmap='inferno', edgecolor='none')
ax1.set_title('Surface Plot of a Paraboloid')
# Plot 2: Sine Triangulation
fig2 = plt.figure()
ax2 = fig2.add_subplot(111, projection='3d')
ax2.plot_trisurf(sine_data[0], sine_data[1], cmap='viridis', edgecolor='none')
ax2.set_title('Surface Triangulation Example')
# Plot 3: Möbius Strip
fig3 = plt.figure()
ax3 = fig3.add_subplot(111, projection='3d')
ax3.plot_surface(*mobi_data, cmap='coolwarm')
ax3.set_title('Möbius Strip')
plt.show()
You may also add to the bottom of ~/.bashrc function activatevenv() {
# Names of possible virtualenv directories
VIRTUALENV_DIRS=("venv/" "env/" ".env/" ".venv/" "${PWD##*/}")
for dir in "${VIRTUALENV_DIRS[@]}"; do
if [[ -d "${dir}" ]]; then
# Found a possible venv directory
# Try activating the venv
if [[ -e "./${dir}/bin/activate" ]]; then
source ./$dir/bin/activate
echo "Virtual environment activated automatically"
break
fi
fi
done
}
# Extension for `cd` command in order to automatically activate virtual env when changing directories.
cd() {
builtin cd $1
# Try activating venv
activatevenv
}
REFERENCES
https://medium.com/@ebimsv/mastering-matplotlib-part-6-exploring-3d-plotting-0423821e2e10

No comments:
Post a Comment