"""
This example demonstrates the use of contour boxplots to visualize the variability in an ensemble of 2D scalar fields.
It generates a synthetic ensemble of scalar fields with Gaussian blobs and visualizes the ensemble contours
using spaghetti plots and contour boxplots.
import necessary libraries
.. code-block:: python
from flask.config import T
import numpy as np
import matplotlib.pyplot as plt
from uvisbox.Modules.ContourBoxplot import contour_boxplot
from uvisbox.Core.CommonInterface import BoxplotStyleConfig
.. code-block:: python
def create_ensemble_scalarfield(image_res=256, n_ensembles=30, sigma_min=5, sigma_max=50):
#
# Create an ensemble of 2D scalar fields with Gaussian blobs in the center.
# Args:
# image_res (int): Resolution of the image (image_res x image_res).
# n_ensembles (int): Number of ensemble members.
# sigma_min (float): Minimum sigma for Gaussian.
# sigma_max (float): Maximum sigma for Gaussian.
# Returns:
# np.ndarray: Array of shape (n_ensembles, image_res, image_res).
#
x = np.linspace(0, image_res-1, image_res)
y = np.linspace(0, image_res-1, image_res)
xx, yy = np.meshgrid(x, y)
grid = np.stack([xx, yy], axis=-1)
ensemble = []
for i in range(n_ensembles):
sigma = np.random.uniform(sigma_min, sigma_max)
cov = np.array([[sigma**2, 0], [0, sigma**2]])
mu = np.array([image_res/2, image_res/2])
inv_cov = np.linalg.inv(cov)
diff = grid - mu
pdf = np.exp(-0.5 * np.sum(diff @ inv_cov * diff, axis=-1))
# Normalize to [-1, 1]
pdf = 2 * (pdf - np.min(pdf)) / (np.max(pdf) - np.min(pdf)) - 1
ensemble.append(pdf)
return np.array(ensemble)
Generate a synthetic ensemble of scalar fields and visualize using spaghetti
.. code-block:: python
# Generate synthetic ensemble of scalar fields
ensemble = create_ensemble_scalarfield(image_res=256, n_ensembles=100, sigma_min=20, sigma_max=100)
# Visualize the ensemble contours using spaghetti
fig, ax = plt.subplots(1, 2, figsize=(10, 4), sharex=True, sharey=True)
# Spaghetti plot - show contours at isovalue = 0.7
for i in range(ensemble.shape[0]):
ax[0].contour(ensemble[i], levels=[0.7], colors='black', linewidths=1, alpha=0.3)
ax[0].set_title("Ensemble Contours (Spaghetti Plot)")
ax[0].set_aspect('equal', adjustable='box')
Calculate and plot the contour boxplot using the new interface
.. code-block:: python
style = BoxplotStyleConfig(
percentiles=[25, 50, 75, 95],
percentile_colormap='Oranges', # Use magma colormap for visualization
show_median=True,
show_outliers=True
)
ax[1] = contour_boxplot(
ensemble,
isovalue=0.7,
boxplot_style=style,
ax=ax[1],
workers=6
)
ax[1].set_title("Contour Boxplot")
ax[1].set_aspect('equal', adjustable='box')
plt.tight_layout()
plt.show()
.. image:: _static/contour_boxplot_example.png
:alt: Contour Boxplot Example
:align: center
"""
# import necessary libraries
from flask.config import T
import numpy as np
import matplotlib.pyplot as plt
from uvisbox.Modules.ContourBoxplot import contour_boxplot
from uvisbox.Core.CommonInterface import BoxplotStyleConfig
[docs]
def create_ensemble_scalarfield(image_res=256, n_ensembles=30, sigma_min=5, sigma_max=50):
"""
Create an ensemble of 2D scalar fields with Gaussian blobs in the center.
Args:
image_res (int): Resolution of the image (image_res x image_res).
n_ensembles (int): Number of ensemble members.
sigma_min (float): Minimum sigma for Gaussian.
sigma_max (float): Maximum sigma for Gaussian.
Returns:
np.ndarray: Array of shape (n_ensembles, image_res, image_res).
"""
x = np.linspace(0, image_res-1, image_res)
y = np.linspace(0, image_res-1, image_res)
xx, yy = np.meshgrid(x, y)
grid = np.stack([xx, yy], axis=-1)
ensemble = []
for i in range(n_ensembles):
sigma = np.random.uniform(sigma_min, sigma_max)
cov = np.array([[sigma**2, 0], [0, sigma**2]])
mu = np.array([image_res/2, image_res/2])
inv_cov = np.linalg.inv(cov)
diff = grid - mu
pdf = np.exp(-0.5 * np.sum(diff @ inv_cov * diff, axis=-1))
# Normalize to [-1, 1]
pdf = 2 * (pdf - np.min(pdf)) / (np.max(pdf) - np.min(pdf)) - 1
ensemble.append(pdf)
return np.array(ensemble)
# Generate a synthetic ensemble of scalar fields and visualize using spaghetti
# Generate synthetic ensemble of scalar fields
ensemble = create_ensemble_scalarfield(image_res=256, n_ensembles=100, sigma_min=20, sigma_max=100)
# Visualize the ensemble contours using spaghetti
fig, ax = plt.subplots(1, 2, figsize=(10, 4), sharex=True, sharey=True)
# Spaghetti plot - show contours at isovalue = 0.7
for i in range(ensemble.shape[0]):
ax[0].contour(ensemble[i], levels=[0.7], colors='black', linewidths=1, alpha=0.3)
ax[0].set_title("Ensemble Contours (Spaghetti Plot)")
ax[0].set_aspect('equal', adjustable='box')
# Calculate and plot the contour boxplot using the new interface
style = BoxplotStyleConfig(
percentiles=[25, 50, 75, 95],
percentile_colormap='Oranges', # Use magma colormap for visualization
show_median=True,
show_outliers=True
)
ax[1] = contour_boxplot(
ensemble,
isovalue=0.7,
boxplot_style=style,
ax=ax[1],
workers=6
)
ax[1].set_title("Contour Boxplot")
ax[1].set_aspect('equal', adjustable='box')
plt.tight_layout()
# plt.savefig("contour_boxplot_example.png", dpi=300)
plt.show()