---
title: Example Gallery
jupyter: python3
# aliases:
  # - ../index.html
html-table-processing: none
filters:
  - line-highlight
---

## Example Gallery {#sec-examples}

Making accessible data representation with **maidr** is easy and straightforward. If you already have data visualization code using **matplotlib** or **seaborn**, you can make your plots accessible with **maidr** in just a few lines of code.

Simply import the `maidr` package and use the `maidr.show()` function to display your plots. **maidr** will automatically generate accessible versions of your plots in your default browser. You can then interact with the accessible versions using keyboard shortcuts (refer to @tbl-shortcuts).

### Bar Plots

#### Simple Bar Plot

```{python}
#| warning: false
#| fig-alt: Bar plot showing the average body mass of penguins by species

import matplotlib.pyplot as plt
import seaborn as sns

# Just import maidr package #<<
import maidr  #<<


# Load the penguins dataset
penguins = sns.load_dataset("penguins")

# Create a bar plot showing the average body mass of penguins by species
plt.figure(figsize=(6, 6))

# Assign the plot to a variable #<<
bar_plot = sns.barplot(  #<<
    x="species", y="body_mass_g", data=penguins, errorbar="sd", palette="Blues_d"
)
plt.title("Average Body Mass of Penguins by Species")
plt.xlabel("Species")
plt.ylabel("Body Mass (g)")

# plt.show()

# Use maidr.show() to display your plot #<<
maidr.show(bar_plot)  #<<
```

#### Vertical Stacked Bar Plot

```{python}
#| warning: false
#| fig-alt: Stacked bar plot of the number of penguins with above average body mass

import matplotlib.pyplot as plt
import numpy as np

import maidr #<<

species = (
    "Adelie",
    "Chinstrap",
    "Gentoo",
)
weight_counts = {
    "Below": np.array([70, 31, 58]),
    "Above": np.array([82, 37, 66]),
}
width = 0.5

fig, ax = plt.subplots()

bottom = np.zeros(3)

for boolean, weight_count in weight_counts.items():
    p = ax.bar(species, weight_count, width, label=boolean, bottom=bottom) #<<
    bottom += weight_count

ax.set_xlabel("Species of Penguins")
ax.set_ylabel("Average Body Mass")

ax.set_title("Number of penguins with above average body mass")
ax.legend(loc="upper right")

maidr.show(p) #<<
```

#### Side-By-Side Dodged Bar Plot

```{python}
#| warning: false
#| fig-alt: Dodged bar plot of penguin weight counts

import matplotlib.pyplot as plt
import numpy as np

import maidr #<<

species: tuple[str, str, str] = (
    "Adelie",
    "Chinstrap",
    "Gentoo",
)
weight_counts: dict[str, np.ndarray] = {
    "Below": np.array([70, 31, 58]),
    "Above": np.array([82, 37, 66]),
}

x: np.ndarray = np.arange(len(species))
total_groups: int = len(weight_counts)
width: float = 0.35

fig, ax = plt.subplots() #<<

offsets: list[float] = [(-width / 2) + i * width for i in range(total_groups)]

for offset, (category, counts) in zip(offsets, weight_counts.items()):
    positions = x + offset
    p = ax.bar(positions, counts, width, label=category) #<<

# Set x-axis labels and title
ax.set_xticks(x)
ax.set_xticklabels(species)
ax.set_xlabel("Species")
ax.set_title("Dodged Bar Plot: Penguin Weight Counts")
ax.legend(loc="upper right")

# Show plot using maidr.show
maidr.show(p) #<<
```

### Histogram

```{python}
# | warning: false
# | fig-alt: Histogram of petal lengths in the Iris dataset

import matplotlib.pyplot as plt
import seaborn as sns

import maidr #<<


# Load the Iris dataset
iris = sns.load_dataset("iris")

# Select the petal lengths
petal_lengths = iris["petal_length"]

# Plot a histogram of the petal lengths
plt.figure(figsize=(6, 6))

hist_plot = sns.histplot(petal_lengths, kde=True, color="blue", binwidth=0.5) #<<

plt.title("Petal Lengths in Iris Dataset")
plt.xlabel("Petal Length (cm)")
plt.ylabel("Frequency")

# plt.show()
maidr.show(hist_plot) #<<
```


### Line Plots

#### Single Line Plot

```{python}
# | fig-alt: Line plot of tips vs total bill for Thursday

import matplotlib.pyplot as plt
import seaborn as sns

import maidr #<<


# Load the 'tips' dataset from seaborn
tips = sns.load_dataset("tips") #<<

# Choose a specific subset of the dataset (e.g., data for 'Thursday')
subset_data = tips[tips["day"] == "Thur"]

# Create a line plot
plt.figure(figsize=(6, 6))
line_plot = sns.lineplot( #<<
    data=subset_data,
    x="total_bill",
    y="tip",
    markers=True,
    style="day",
    legend=False,
)
plt.title("Tips vs Total Bill (Thursday)")
plt.xlabel("Total Bill")
plt.ylabel("Tip")

# plt.show()
maidr.show(line_plot) #<<
```

#### Multiline Plot

```{python}
#| fig-alt: Multiline plot of three series

import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
import seaborn as sns

import maidr #<<
# Create sample data points
x = np.array([1, 2, 3, 4, 5, 6, 7, 8])
y1 = np.array([2, 4, 1, 5, 3, 7, 6, 8])
y2 = np.array([1, 3, 5, 2, 4, 6, 8, 7])
y3 = np.array([3, 1, 4, 6, 5, 2, 4, 5])

# Convert to pandas DataFrame for seaborn
data = pd.DataFrame(
    {
        "x": np.tile(x, 3),
        "y": np.concatenate([y1, y2, y3]),
        "series": np.repeat(["Series 1", "Series 2", "Series 3"], len(x)),
    }
)

# Create the plot
plt.figure(figsize=(6, 6))

# Use seaborn lineplot for multiple lines
lineplot = sns.lineplot(
    x="x", y="y", hue="series", style="series", markers=True, dashes=True, data=data
)

# Customize the plot
plt.title("Seaborn Multiline Plot")
plt.xlabel("X values")
plt.ylabel("Y values")

# Display the plot using maidr
maidr.show(lineplot) #<<

```

### Heat Map

```{python}
#| fig-alt: Heatmap of model scores by task

import matplotlib.pyplot as plt
import seaborn as sns

import maidr #<<

# Load an example dataset from seaborn
glue = sns.load_dataset("glue").pivot(index="Model", columns="Task", values="Score")

# Plot a heatmap
plt.figure(figsize=(8, 8))
heatmap = sns.heatmap(glue, annot=True, fill_label="Score") #<<
plt.title("Model Scores by Task")

# Show the plot
# plt.show()
maidr.show(heatmap) #<<
```

### Box Plot

* **Note**: Visual highlight feature has not been implemented in the box plot yet.

```{python}
#| fig-alt: Box plot of petal length by species from the Iris dataset


import matplotlib.pyplot as plt
import seaborn as sns
from seaborn import load_dataset

import maidr #<<

# Load the iris dataset
iris = load_dataset("iris")

# Create the horizontal boxplot
horz_box_plot = sns.boxplot(x="petal_length", y="species", data=iris, orient="h") #<<
plt.ylabel("Species")
plt.xlabel("Petal Length")
plt.title("Petal Length by Species from Iris Dataset")
# plt.show()

# Show the plot
maidr.show(horz_box_plot) #<<
```

### Scatter Plot

```{python}
#| fig-alt: Scatter plot of Iris sepal length vs sepal width

import matplotlib.pyplot as plt
import seaborn as sns

import maidr #<<

# Create a scatter plot
scatter_plot = sns.scatterplot( #<<
    data=iris, x="sepal_length", y="sepal_width", hue="species"
)

# Adding title and labels (optional)
plt.title("Iris Sepal Length vs Sepal Width")
plt.xlabel("Sepal Length")
plt.ylabel("Sepal Width")

# Show the plot
# plt.show()
maidr.show(scatter_plot) #<<
```

### Multi-Layered Plots

```{python}
#| fig-alt: Multi-layered plot with bar and line plots

import matplotlib.pyplot as plt
import numpy as np
import maidr #<<

# Generate sample data
x = np.arange(5)
bar_data = np.array([3, 5, 2, 7, 3])
line_data = np.array([10, 8, 12, 14, 9])

# Create a figure and a set of subplots
fig, ax1 = plt.subplots(figsize=(8, 5)) #<<

# Create the bar chart on the first y-axis
ax1.bar(x, bar_data, color="skyblue", label="Bar Data")
ax1.set_xlabel("X values")
ax1.set_ylabel("Bar values", color="blue")
ax1.tick_params(axis="y", labelcolor="blue")

# Create a second y-axis sharing the same x-axis
ax2 = ax1.twinx()

# Create the line chart on the second y-axis
ax2.plot(x, line_data, color="red", marker="o", linestyle="-", label="Line Data")
ax2.set_xlabel("X values")
ax2.set_ylabel("Line values", color="red")
ax2.tick_params(axis="y", labelcolor="red")

# Add title and legend
plt.title("Multilayer Plot Example")

# Add legends for both axes
lines1, labels1 = ax1.get_legend_handles_labels()
lines2, labels2 = ax2.get_legend_handles_labels()
ax1.legend(lines1 + lines2, labels1 + labels2, loc="upper left")

# Adjust layout
fig.tight_layout()

maidr.show(fig) #<<
```

### Multi-Panel Plots (Multiple Subplots)

```{python}
#| fig-alt: Multi-panel plot with line and bar plots

import matplotlib.pyplot as plt
import numpy as np
import seaborn as sns

import maidr #<<

# Set the plotting style
sns.set_theme(style="whitegrid")

# Data for line plot
x_line = np.array([1, 2, 3, 4, 5, 6, 7, 8])
y_line = np.array([2, 4, 1, 5, 3, 7, 6, 8])
line_data = {"x": x_line, "y": y_line}

# Data for first bar plot
categories = ["A", "B", "C", "D", "E"]
values = np.random.rand(5) * 10
bar_data = {"categories": categories, "values": values}

# Data for second bar plot
categories_2 = ["A", "B", "C", "D", "E"]
values_2 = np.random.randn(5) * 100
bar_data_2 = {"categories": categories_2, "values": values_2}

# Create a figure with 3 subplots arranged vertically
fig, axs = plt.subplots(3, 1, figsize=(6, 12)) #<<

# First panel: Line plot using seaborn
sns.lineplot(x="x", y="y", data=line_data, color="blue", linewidth=2, ax=axs[0])
axs[0].set_title("Line Plot: Random Data")
axs[0].set_xlabel("X-axis")
axs[0].set_ylabel("Values")

# Second panel: Bar plot using seaborn
sns.barplot(
    x="categories", y="values", data=bar_data, color="green", alpha=0.7, ax=axs[1]
)
axs[1].set_title("Bar Plot: Random Values")
axs[1].set_xlabel("Categories")
axs[1].set_ylabel("Values")

# Third panel: Bar plot using seaborn
sns.barplot(
    x="categories", y="values", data=bar_data_2, color="blue", alpha=0.7, ax=axs[2]
)
axs[2].set_title("Bar Plot 2: Random Values")  # Fixed the typo in the title
axs[2].set_xlabel("Categories")
axs[2].set_ylabel("Values")

# Adjust layout to prevent overlap
plt.tight_layout()

# Display the figure
maidr.show(fig) #<<
```

### Facet Plot
```{python}
#| fig-alt: Facet Plot Example using maidr

import matplotlib.pyplot as plt
import numpy as np

import maidr #<<

categories = ["A", "B", "C", "D", "E"]

np.random.seed(42)
data_group1 = np.random.rand(5) * 10
data_group2 = np.random.rand(5) * 100
data_group3 = np.random.rand(5) * 36
data_group4 = np.random.rand(5) * 42

data_sets = [data_group1, data_group2, data_group3, data_group4]
condition_names = ["Group 1", "Group 2", "Group 3", "Group 4"]

fig, axs = plt.subplots(2, 2, figsize=(7, 7), sharey=True, sharex=True)
axs = axs.flatten()

all_data = np.concatenate(data_sets)
y_min, y_max = np.min(all_data) * 0.9, np.max(all_data) * 1.1

# Create a bar plot in each subplot
for i, (data, condition) in enumerate(zip(data_sets, condition_names)):
    axs[i].bar(categories, data, color=f"C{i}", alpha=0.7)
    axs[i].set_title(f"{condition}")
    axs[i].set_ylim(y_min, y_max)  # Set consistent y-axis limits

    # Add value labels on top of each bar
    for j, value in enumerate(data):
        axs[i].text(
            j,
            value + (y_max - y_min) * 0.02,
            f"{value:.1f}",
            ha="center",
            va="bottom",
            fontsize=9,
        )

# Add common labels
fig.text(0.5, 0.04, "Categories", ha="center", va="center", fontsize=14)
fig.text(
    0.06, 0.5, "Values", ha="center", va="center", rotation="vertical", fontsize=14
)

# Add a common title
fig.suptitle("Facet Plot: Bar Charts by Condition", fontsize=16)

# Adjust layout
plt.tight_layout(rect=(0.08, 0.08, 0.98, 0.95))

maidr.show(fig) #<<
```

### Candlestick Chart

```{python}
#| warning: false
#| fig-alt: Candlestick chart showing stock price movements with volume

import mplfinance as mpf
import pandas as pd

import maidr #<<

# Load the sample data
daily = pd.read_csv("../example/candle_stick/volcandat.csv", index_col=0, parse_dates=True)

# Create the candlestick chart with moving averages and volume
fig, ax = mpf.plot(
    daily,
    type="candle",
    volume=True,
    mav = (3,6,9),
    returnfig=True,
    ylabel="Price ($)",
    ylabel_lower="Volume",
    xlabel="Date",
    title="Stock Price with Volume",
)  #<<
fig.tight_layout()

# Display with maidr
maidr.show(fig) #<<
```

## Reactive Dashboard

### Shiny

Check out [a reactive Shiny dashboard example with maidr](https://xabilitylab.shinyapps.io/a11y_dashboard/) and its source code is available on [GitHub](https://github.com/xability/a11y_dashboard).

### Streamlit

Check out [this Streamlit dashboard](https://0193dbe9-1a63-183e-ba7f-b62075dd1d71.share.connect.posit.cloud/) with maidr, and its source code is available on [GitHub](https://github.com/xability/maidr_streamlit).

    * Note: `Streamlit` framework has some "Unlabeled 0 Button" which does not have to do with our maidr package. This issue needs to be addressed by the `Streamlit` team.

## Interactive Computing (Jupyter Notebooks, Jupyter Labs, Google Colab)

Check out [this interactive notebook in Google Colab](https://colab.research.google.com/drive/1In85HRpSLgOcLbLudSdfO3axYtkOlua1?usp=sharing).

## Other Examples

We provide [some example code](https://github.com/xability/py-maidr/blob/main/example) for using py-maidr with matplotlib, seaborn, Jupyter Notebook, Quarto, Shiny, and Streamlit.

## Keyboard Shortcuts and Controls

To interact with the plots using maidr, follow these steps:

1. Press the **Tab** key to focus on the plot element.
2. Use the **arrow keys** to move around the plot.
3. Press **B** to toggle Braille mode.
4. Press **T** to toggle Text mode.
5. Press **S** to toggle Sonification (tones) mode.
6. Press **R** to toggle Review mode.

Below is a detailed list of keyboard shortcuts for various functions:

| Function | Windows and Linux Key | Mac Key |
|:---|:---|:---|
| Toggle Braille Mode | b | b |
| Toggle Text Mode | t | t |
| Toggle Sonification Mode | s | s |
| Toggle Review Mode | r | r |
| Move around plot | Arrow keys | Arrow keys |
| Go to the very left right up down | Ctrl + Arrow key | CMD + Arrow key |
| Select the first element | Ctrl + Home | CMD + Home |
| Select the last element | Ctrl + End | CMD + End |
| Repeat current sound | Space | Space |
| Auto-play outward in direction of arrow | Ctrl + Shift + Arrow key | CMD + Shift + Arrow key |
| Stop Auto-play | Ctrl | Ctrl |
| Auto-play speed up | Period (.) | Period (.) |
| Auto-play speed down | Comma (,) | Comma (,) |
| Auto-play speed reset | Slash (/) | Slash (/) |
| Check label for the title of current plot | l t | l t |
| Check label for the x axis of current plot | l x | l x |
| Check label for the y axis of current plot | l y | l y |
| Check label for the fill (z) axis of current plot | l f | l f |
| Switch to next layer | PageUp | PageUp |
| Switch to previous layer | PageDown | PageDown |
| Move around subplot list | Arrow keys | Arrow keys |
| Activate selected subplot in the list | Enter | Enter |
| Escape from current subplot to return to the subplot list | ESC | ESC |
| Open settings | Ctrl + comma (,) | CMD + comma (,) |
| Open Chat View | Question (?) | Question (?) |
| Open keyboard help | Ctrl + Slash (/) | CMD + Slash (/) |

Table: Keyboard Shortcuts {#tbl-shortcuts}

## Demo Video

{{< video https://youtu.be/NR2G4lNolf4 >}}

## Bug Report

If you encounter a bug, have usage questions, or want to share ideas to make this package better, please feel free to file an [issue](https://github.com/xability/py-maidr/issues).

## Code of Conduct

Please note that the **maidr** project is released with a [contributor code of conduct](https://www.contributor-covenant.org/version/2/1/code_of_conduct/).<br>By participating in this project you agree to abide by its terms.

## 📄 License

**maidr** is licensed under the GPL3 license.

© [(x)Ability Design Lab](https://xability.github.io/).

## 🏛️ Governance

This project is primarily maintained by [JooYoung Seo](https://ischool.illinois.edu/people/jooyoung-seo) and [Saairam Venkatesh](https://github.com/SaaiVenkat).
Other authors may occasionally assist with some of these duties.
