Plotting Tutorial#

This tutorial demonstrates how to use the plotting capabilities of the AFL.double_agent package to visualize compositional and scattering data.

Introduction#

The AFL.double_agent.plotting module provides a variety of plotting functions for visualizing materials data. It supports:

  • Compositional data visualization (scatter and surface plots)

  • Small-angle scattering data visualization

  • Both 2D and 3D plots

  • Ternary plots for three-component systems

  • Multiple backends (Matplotlib and Plotly)

In this tutorial, we’ll explore these capabilities using example datasets.

Google Colab Setup#

Only uncomment and run the next cell if you are running this notebook in Google Colab or if don’t already have the AFL-agent package installed.

[ ]:
# !pip install git+https://github.com/usnistgov/AFL-agent.git

General Setup#

First, let’s import the necessary modules and load our example dataset:

[1]:
import numpy as np
import matplotlib.pyplot as plt
import xarray as xr

# Import the plotting module
from AFL.double_agent.plotting import plot, plot_scatter_mpl, plot_surface_mpl, plot_sas_mpl
from AFL.double_agent.plotting import plot_scatter_plotly, plot_surface_plotly, plot_sas_plotly

# Load the example dataset
from AFL.double_agent.data import example_dataset1

import plotly.io as pio
pio.renderers.default = "iframe_connected"
# pio.renderers.default = "plotly_mimetype"

# Load the dataset
ds = example_dataset1()

# Display the dataset structure
ds
[1]:
<xarray.Dataset> Size: 164kB
Dimensions:              (sample: 100, component: 2, x: 150, grid: 2500)
Coordinates:
  * component            (component) <U1 8B 'A' 'B'
  * x                    (x) float64 1kB 0.001 0.001047 0.001097 ... 0.9547 1.0
Dimensions without coordinates: sample, grid
Data variables:
    composition          (sample, component) float64 2kB ...
    ground_truth_labels  (sample) int64 800B ...
    measurement          (sample, x) float64 120kB ...
    composition_grid     (grid, component) float64 40kB ...

The example dataset contains compositional data and measurements that we can use for our plots.

Compositional Data Visualization#

Scatter Plots#

Let’s start with a simple scatter plot of our compositional data using Matplotlib:

[2]:
# Create a scatter plot using Matplotlib
plt.figure(figsize=(8, 6))
artists = plot_scatter_mpl(
    dataset=ds,
    component_variable='composition',
    labels='ground_truth_labels',
    discrete_labels=True
)
plt.title('Composition Scatter Plot (Matplotlib)')
plt.show()

<Figure size 800x600 with 0 Axes>
../_images/tutorials_visualization_6_1.png

We can also create the same plot using the unified plot function:

[3]:
# Create a scatter plot using the unified plot function
plt.figure(figsize=(8, 6))
artists = plot(
    dataset=ds,
    kind='scatter',
    backend='mpl',
    component_variable='composition',
    labels='ground_truth_labels',
    discrete_labels=True
)
plt.title('Composition Scatter Plot (Unified API)')
plt.show()

<Figure size 800x600 with 0 Axes>
../_images/tutorials_visualization_8_1.png

Now, let’s create an interactive scatter plot using Plotly.

[4]:
# Create a scatter plot using Plotly
fig = plot_scatter_plotly(
    dataset=ds,
    component_variable='composition',
    labels='ground_truth_labels',
    discrete_labels=True
)
fig.update_layout(title='Composition Scatter Plot (Plotly)')
fig.show()

Surface Plots#

Surface plots are useful for visualizing continuous fields over compositional space:

[5]:
# Create a surface plot using Matplotlib
plt.figure(figsize=(8, 6))
artists = plot_surface_mpl(
    dataset=ds,
    component_variable='composition',
    labels='ground_truth_labels'
)
plt.colorbar(artists)
plt.title('Composition Surface Plot (Matplotlib)')
plt.show()
<Figure size 800x600 with 0 Axes>
../_images/tutorials_visualization_13_1.png

And with Plotly:

[6]:
# Create a surface plot using Plotly
fig = plot_surface_plotly(
    dataset=ds,
    component_variable='composition',
    labels='ground_truth_labels'
)
fig.update_layout(title='Composition Surface Plot (Plotly)')
fig.show()

Small-Angle Scattering Data Visualization#

The measurement variable in our dataset can be treated as scattering data for demonstration purposes.

Log-Log Plots#

Log-log plots are commonly used for scattering data:

[7]:
# Create a log-log plot using Matplotlib
plt.figure(figsize=(8, 6))
artists = plot_sas_mpl(
    dataset=ds,
    plot_type='loglog',
    x='x',
    y='measurement',
    xlabel='q (Å⁻¹)',
    ylabel='Intensity (a.u.)',
    legend=False,
)
plt.title('Scattering Data Log-Log Plot (Matplotlib)')
plt.show()

../_images/tutorials_visualization_17_0.png

And with Plotly:

[8]:
# Create a log-log plot using Plotly
fig = plot_sas_plotly(
    dataset=ds,
    plot_type='loglog',
    x='x',
    y='measurement',
    xlabel='q (Å⁻¹)',
    ylabel='Intensity (a.u.)'
)
fig.update_layout(title='Scattering Data Log-Log Plot (Plotly)')
fig.show()

Waterfall Plots#

Waterfall plots are useful for comparing multiple scattering curves:

[9]:
# Create a log waterfall plot using Matplotlib
plt.figure(figsize=(10, 8))
artists = plot_sas_mpl(
    dataset=ds,
    plot_type='logwaterfall',
    x='x',
    y='measurement',
    xlabel='q (Å⁻¹)',
    ylabel='Intensity (a.u.)',
    base=5, # Separation factor between curves
    legend=False,
)
plt.title('Scattering Data Log Waterfall Plot (Matplotlib)')
plt.show()

../_images/tutorials_visualization_21_0.png

And with Plotly:

[10]:
# Create a log waterfall plot using Plotly
fig = plot_sas_plotly(
    dataset=ds,
    plot_type='logwaterfall',
    x='x',
    y='measurement',
    xlabel='q (Å⁻¹)',
    ylabel='Intensity (a.u.)',
    base=5  # Separation factor between curves
)
fig.update_layout(title='Scattering Data Log Waterfall Plot (Plotly)')
fig.show()

Linear Plots#

For some data, linear plots might be more appropriate. This is often used when the data has been log-scaled already.

[32]:
# Create a linear plot using Matplotlib

plt.figure(figsize=(8, 6))
artists = plot_sas_mpl(
    dataset=ds,
    plot_type='linlin',
    x='x',
    y='measurement',
    xlabel='q (Å⁻¹)',
    ylabel='Intensity (a.u.)'
)
plt.title('Scattering Data Linear Plot (Matplotlib)')
plt.show()

../_images/tutorials_visualization_25_0.png

Advanced Features#

3D Plots for Three-Component Systems#

For three-component systems, we can create 3D plots:

[33]:
# Create a synthetic three-component dataset
n_samples = 100
components = np.random.random((n_samples, 3))
# Normalize to sum to 1
components = components / components.sum(axis=1, keepdims=True)

# Create labels
labels = np.zeros(n_samples)
labels[components[:, 0] > 0.6] = 1
labels[components[:, 1] > 0.6] = 2

# Create the dataset
three_comp_ds = xr.Dataset(
    data_vars={
        'compositions': (['sample', 'component'], components)
    },
    coords={
        'component': ['A', 'B', 'C'],
        'labels': (['sample'], labels)
    }
)

# Create a 3D scatter plot (non-ternary)
fig = plot_scatter_plotly(
    dataset=three_comp_ds,
    component_variable='compositions',
    labels='labels',
    discrete_labels=True,
    ternary=False  # Use 3D Cartesian plot instead of ternary
)
fig.update_layout(title='Three-Component Scatter Plot (3D)')
fig.show()

Ternary Plots#

For three-component systems, ternary plots are often more intuitive:

[34]:
fig = plot_scatter_plotly(
    dataset=three_comp_ds,
    component_variable='compositions',
    labels='labels',
    discrete_labels=True,
    ternary=True  # Use ternary plot
)
fig.update_layout(title='Three-Component Scatter Plot (Ternary)')
fig.show()

Conclusion#

In this tutorial, we’ve explored the plotting capabilities of the AFL.double_agent package. We’ve seen how to:

  • Create scatter and surface plots for compositional data

  • Visualize small-angle scattering data with various plot types

  • Work with both 2D and 3D plots

  • Create ternary plots for three-component systems

  • Use both Matplotlib and Plotly backends

  • Customize plots to suit specific needs

The unified plot function provides a convenient interface to all these capabilities, making it easy to switch between plot types and backends.

For more details on the available plotting functions and their parameters, refer to the API documentation.