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
fig, ax = plt.subplots(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", ax=ax
)
ax.set_title("Average Body Mass of Penguins by Species")
ax.set_xlabel("Species")
ax.set_ylabel("Body Mass (g)")
# plt.show() now renders accessible maidr output
plt.show()
# Uncomment the following line to save and share the accessible version of your plot with others!
# maidr.save_html(bar_plot, "output.html") py-maidr: Accessible Data Visualization for Python
maidr: Data Insight for All
Are you eager to uncover new insights from data science but frustrated by visual-only data representations? Do you want to make your data visualizations accessible to everyone, including those who are blind or low-vision? If so, maidr is for you!
maidr (pronounced as ‘mader’) is an accessible framework for multimodal data representation. With maidr, blind and sighted users can easily augment data visualizations into touchable (Braille), readable (text), audible (sonification), and conversational (AI) formats.
To learn more about maidr framework and its scientific background, please visit the original maidr JavaScript engine repo.
The following summarizes the key features and design principles of Py maidr:
Accessibility: maidr is designed to be accessible to both blind and sighted users from the ground up. Beyond the passive consumption level, blind users can also independently create, modify, and share data visualizations with others.
Inclusivity: maidr does not pursue a special version for blind users. Instead, it provides a unified interface that supports both visual and non-visual data exploration. This way, blind and sighted users can work together on the same data science projects.
Integration: maidr seamlessly integrates with the popular and mainstream data science environments (e.g., Python, pandas, and NumPy) as well as data visualization libraries in Python like matplotlib and seaborn.
Unintrusiveness: maidr does not require changes to existing core data visualization code. Without needing to reconstruct an accessible version separately, you can just
import maidrand callplt.show()as usual — maidr’s custom backend automatically renders your plots accessibly. Blind and sighted users can use and share the same visualization codebase in their shared data science projects.Synchronization: maidr treats visualization as one of the multimodal data representations and ensures that all representations (e.g., visual, tactile, textual, audible) cursor and braille routing key positions are synchronized across different modalities.
Reactivity: maidr supports widely adopted reactive and interactive computing including Jupyter Notebooks, Jupyter Labs, Google Colab, Streamlit dashboard, and Shiny dashboard. maidr also supports interactive computing inside code editors, such as Visual Studio Code.
Reproducibility: maidr supports the generation of accessible data visualizations as part of the reproducible data science workflow with Quarto scientific publishing system. You can easily create accessible data representations within your reproducible reports, website blogs, slides, e-books, dashboards, and more.
Scalability: maidr supports a wide range of data visualization types, including bar plots, histograms, line plots, box plots, violin plots, heatmaps, scatter plots, and more. maidr is designed to be extensible to support new visualization types. Multi-figure and multi-layer visualizations are also supported.
Our core philosophy is to make data science accessible to everyone, regardless of their visual dis/abilities. We believe that by making data visualizations accessible, we can empower blind and sighted users to work together on data science projects, share insights, and make data-driven decisions collaboratively.
Supported Data Visualization Libraries
We currently support the following data visualization libraries in Python:, and we are working on adding support for more libraries in the future:
Matplotlib
One-factor bar plot having one x (categorical) and one y (numerical/count) axis.
Stacked bar plot having one x (categorical) and one y (numerical/count) axis with multiple data series stacked vertically.
Dodged (grouped) bar plot having one x (categorical) and one y (numerical/count) axis with multiple data series displayed side-by-side.
One distribution histogram having one x (numerical) and y (numerical/frequency) axis.
KDE (Kernel Density Estimation) plot having one x (numerical) and one y (density) axis showing probability density curves.
Single line plot having one x (numerical) and one y (numerical) axis.
Multi-line plot having one x (numerical) and one y (numerical) axis with multiple data series on the same axes.
Step plot having one x (numerical) and one y (numerical or ordinal) axis, for piecewise-constant values that are held over an interval and then jump — e.g. a hypnogram of sleep stage against time. Named y tick labels are announced as level names in place of the numeric level. Recognised from matplotlib’s
drawstyle="steps-*"(includingax.step()), Plotly’sline_shape, and Altair’sinterpolate.Vertical box plot having one x (categorical) and one y (numerical) axis.
Horizontal box plot having one x (numerical) and one y (categorical) axis.
- Note: For box plots, the categorical variable can be either single-class or multi-class. We support both cases.
Violin plot having one x (categorical) and one y (numerical) axis, combining a KDE density curve with embedded box plot statistics.
Heatmap having one x (categorical) and one y (categorical) and z (numerical) axis.
Scatter plot having one x (numerical) and one y (numerical) axis.
Regression plot having one x (numerical) and one y (numerical) axis with scatter points and fitted regression line.
Candlestick chart having one x (time/date) and four y (numerical) axes (open, high, low, close) for financial data visualization (using mplfinance).
Multi-layered plots combining different plot types on the same figure with shared axes.
Multi-panel plots (subplots) with multiple charts in a grid layout having independent axes.
Facet plots showing the same chart type across different data subsets with shared axis scales.
Seaborn
sns.barplot(): One-factor bar plot having one x (categorical) and one y (numerical/count) axis.sns.countplot(): Count plot having one x (categorical) and one y (count) axis showing the frequency of categorical data.sns.histplot(): One distribution histogram having one x (numerical) and y (numerical/frequency) axis.sns.kdeplot(): KDE (Kernel Density Estimation) plot having one x (numerical) and one y (density) axis showing probability density curves.sns.lineplot(): Single line plot having one x (numerical) and one y (numerical) axis.sns.boxplot(..., orient="v"): Vertical box plot having one x (categorical) and one y (numerical) axis.sns.boxplot(..., orient="h"): Horizontal box plot having one x (numerical) and one y (categorical) axis.- Note: For box plots, the categorical variable can be either single-class or multi-class. We support both cases.
sns.violinplot(): Violin plot having one x (categorical) and one y (numerical) axis, combining a KDE density curve with embedded box plot statistics. Supports vertical and horizontal orientations.sns.heatmap(): Heatmap having one x (categorical) and one y (categorical) and z (numerical) axis.sns.scatterplot(): Scatter plot having one x (numerical) and one y (numerical) axis.sns.regplot(): Regression plot having one x (numerical) and one y (numerical) axis with scatter points and fitted regression line.
Altair
py-maidr ships an Altair adapter that compiles single-view (alt.Chart) and layered (alt.LayerChart / c1 + c2) specs to MAIDR-instrumented Vega-Lite output. Use maidr.show(chart) (or maidr.save_html(chart, ...)) to render an accessible version of any supported Altair chart.
One-factor bar plot (
mark_bar) with one x (categorical) and one y (numerical/count) axis.Dodged (grouped) bar plot using
xOffsetto separate series side-by-side.Stacked bar plot — same encoding as the dodged case but without
xOffset; series stack vertically.Count plot (
mark_barwithcount()aggregate) showing the frequency of categorical data.Histogram (
mark_barwithbin=True) having one x (numerical/binned) and one y (count/density) axis.KDE plot using
transform_density, with single-series and multi-series (color-grouped) variants supported.Vertical and horizontal box plots (
mark_boxplot).Heatmap built as a
LayerChartofmark_rect+mark_textover categorical x/y with a numerical color/z encoding.Single-line plot (
mark_line) and multi-line plots — both the per-series-layer pattern and the single-mark-with-color-encoding pattern.Scatter plot (
mark_point/mark_circle).Multi-layered plots combining
mark_point+mark_line(e.g. line-with-points overlays) on aLayerChart.Regression-style scatter overlaid with a
transform_loesssmoothing line on aLayerChart.
Facet, repeat, and concat composite specs (alt.FacetChart, alt.RepeatChart, alt.ConcatChart, alt.HConcatChart, alt.VConcatChart) are not supported by the adapter; only alt.Chart and alt.LayerChart instances are accepted by maidr.show() / maidr.save_html().
Additional Libraries
- mplfinance: Candlestick charts having one x (time/date) and four y (numerical) axes (open, high, low, close) for financial data with support for moving averages and volume data.
Installation
Python 3.x is required to use maidr. After installing Python, you can install maidr using the following commands in your terminal:
# install the latest release from PyPI
pip install -U maidr# or install the development version from GitHub
pip install -U git+https://github.com/xability/py-maidr.gitGetting Started
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 maidr and call plt.show() as usual. maidr automatically activates a custom matplotlib backend, so plt.show() renders accessible HTML output (with sonification, braille, and tactile support) instead of a static image. You can then interact with the accessible plots using keyboard shortcuts (refer to Table 1).
Check more examples in the galleries.
Sample Bar Plot
Custom Backend
When you import maidr, a custom matplotlib backend is automatically activated. This means plt.show() renders accessible HTML output instead of a static image.
Switching Back to the Default Renderer
If you want to temporarily use the default matplotlib renderer (e.g. for unsupported plot types or debugging), you can switch the backend:
In Jupyter notebooks:
maidr.set_backend(use_maidr=False) # plt.show() now renders static inline images
maidr.set_backend(use_maidr=True) # plt.show() renders accessible maidr output againIn Python scripts (non-notebook):
maidr.set_backend(use_maidr=False) # plt.show() now opens the native image viewer (e.g. macOS, TkAgg)
maidr.set_backend(use_maidr=True) # plt.show() renders accessible maidr output againmaidr.show() always renders accessible output regardless of the active backend. You only need maidr.set_backend() to control the behavior of plt.show().
If you want to set the backend manually, use matplotlib.use("module://maidr.backend"). The shorthand matplotlib.use("maidr") requires matplotlib >= 3.9.
Unsupported Plot Types
For plot types not yet supported by maidr (e.g. pie charts, contour plots, 3D plots), plt.show() will automatically fall back to displaying a static image and emit a warning. No code changes are needed — your plots will always be visible.
Offline Use and the JavaScript Bundle
Accessible output needs the maidr.js library. render(), show(), and save_html() accept use_cdn= to control where it comes from:
use_cdn |
Where maidr.js comes from |
|---|---|
"auto" (default) |
The jsDelivr CDN, falling back to the bundled copy in the browser if the CDN is unreachable. |
True |
The CDN only, with no offline fallback. |
False |
The copy bundled inside the installed maidr package. Use this in air-gapped environments. |
Set the default for a whole session with maidr.set_use_cdn(...) or the MAIDR_USE_CDN environment variable.
No stylesheet accompanies the script. maidr styles its interface at runtime, so there is nothing static to link; the one stylesheet it does use — KaTeX, which renders LaTeX in AI chat responses — is fetched by maidr.js itself, on demand, from whichever directory it was loaded from. save_html(use_cdn=False) copies it into lib/ alongside maidr.js so that keeps working offline, and in notebooks init_notebook() stashes it in the page for the same reason: an iframe rendered from srcdoc has no base URL for the runtime to resolve against.
That runtime fetch is what 3.75.1 introduced, when KaTeX moved out of maidr.css and left it a placeholder. Pinning MAIDR_CDN_VERSION to anything older gets a maidr.js that expects the stylesheet to be linked for it — and py-maidr no longer links one, so LaTeX in AI chat responses renders unstyled. Nothing else is affected: the interface has been styled at runtime throughout. py-maidr logs a warning once per process when a pin names such a version.
Which version the CDN serves
On the CDN paths (use_cdn=True and "auto"), py-maidr resolves the current published maidr version and emits a versioned URL such as maidr@3.74.0/dist/maidr.js.
This matters because the CDN serves the mutable maidr@latest URL with a seven-day cache lifetime. A browser that had loaded it before would keep replaying its cached copy for up to a week after a new release — so a versioned URL is what guarantees you actually get the current build.
Resolving the version makes a single outbound HTTPS request, the first time a CDN URL is built for a rendered plot. It is cached for the rest of the process and falls back to the @latest URL if it fails — so a blocked or slow network costs you a one-time delay, never an error.
import maidr makes no request, even in a notebook: init_notebook() pins its tags to the version bundled in the wheel, which needs no lookup and is still immutable.
MAIDR_CDN_TIMEOUT (default 3 seconds) is shared across the lookup rather than applied per attempt, so a fallback endpoint cannot multiply the wait. Treat it as approximate rather than a ceiling: the underlying timeout applies per socket operation — connect, TLS handshake, read — so an endpoint that stalls just under the limit at each step can overrun it by a small multiple.
In sandboxed or egress-blocked environments (CI, air-gapped machines), MAIDR_CDN_VERSION=bundled is usually the best setting: zero requests, and still an immutable URL so caching behaves correctly. MAIDR_USE_CDN=false skips the CDN altogether, and MAIDR_CDN_VERSION=latest keeps the CDN but not the lookup.
One exception is worth knowing about: Altair charts always load maidr.js from the CDN. That adapter has no bundled/offline path — use_cdn and MAIDR_USE_CDN are not plumbed through it — so MAIDR_USE_CDN=false will not make an Altair chart self-contained. MAIDR_CDN_VERSION=bundled does still remove the version lookup for Altair, which is why it is the better setting when any part of your work is air-gapped.
render_maidr calls into the synchronous render path, so the one-time lookup happens on the event loop and blocks it for up to MAIDR_CDN_TIMEOUT. Set MAIDR_CDN_VERSION=bundled at startup for Shiny apps to avoid that entirely.
bundle_status() is the one deliberate exception: it resolves even when pinned, because “how does my bundle compare to what’s published?” has no answer otherwise. Pass resolve=False if you need it silent.
Pin the version yourself when you need reproducible output:
maidr.set_cdn_version("3.74.0") # a specific published version
maidr.set_cdn_version("bundled") # whatever this package ships with
maidr.set_cdn_version("latest") # skip resolution, emit the mutable @latest URL
maidr.set_cdn_version(None) # back to resolving automaticallyset_cdn_version() and set_use_cdn() write module-level state shared by everything in the interpreter. In a server handling concurrent sessions — a Shiny app, for instance — one session calling a setter changes what every other session renders.
For multi-session servers, configure once at startup via the environment variables below, or pass use_cdn= explicitly on each render() / save_html() call, rather than calling the setters per request.
Keeping the bundled copy current
The bundled maidr.js is refreshed when py-maidr is released, so it can fall behind between releases. Since the offline fallback is what runs whenever the CDN is disabled or unreachable, py-maidr warns once per session when the bundled copy has drifted a long way behind the published release. Upgrading py-maidr picks up a fresher bundle.
-W error
It is emitted with warnings.warn(..., UserWarning). If you run Python with -W error, or set filterwarnings = ["error"] in your pytest config, a stale bundle will make render() / save_html() raise rather than warn. Set MAIDR_BUNDLE_STALE_WARNING=0 to turn it off, or filter the category precisely with maidr.MaidrBundleStaleWarning.
It is only raised as a warning when the bundle genuinely runs (use_cdn=False). Under use_cdn="auto" the CDN copy normally loads instead, so the drift is reported to the logger rather than as a warning that could redden a test suite over code that never executed.
The warning needs to know what the current published release is, and it will never make a network request to find out — that would defeat use_cdn=False. So it only fires when a real lookup has already happened in that session.
Pinning does not help, and in fact guarantees silence: a pin short-circuits resolution, so nothing ever establishes what is published. A session that is pinned, or that only ever uses use_cdn=False, stays silent no matter how old its bundle is. That is the air-gapped case, and it is the one this warning cannot reach by itself. Check it explicitly instead:
maidr.bundle_status()
# BundleStatus(bundled='3.73.0', published='3.74.0', is_behind=True, is_stale=False)bundle_status() resolves the published version itself (one request), so it works even in a session that has never touched the CDN. Pass resolve=False if you want the comparison without any network access, accepting published=None when it isn’t already known.
The resolved version is looked up once per process, and the staleness warning fires at most once. A long-lived session — a Jupyter kernel, a Shiny app — will not notice a newer release or a freshly upgraded py-maidr until it restarts. Call maidr.reset_cdn_version_cache() to force one more lookup, or restart the kernel; note that the warning itself does not re-arm either way.
Environment variables
| Variable | Effect |
|---|---|
MAIDR_USE_CDN |
Default for use_cdn: auto, 1/true, or 0/false. |
MAIDR_CDN_VERSION |
Pin the CDN version — bundled is the recommended setting for restricted networks (does not affect bundle_status(), which always resolves unless passed resolve=False): a version such as 3.74.0, bundled, or latest to skip resolution. If bundled is set but the installed VERSION file is missing or unreadable, py-maidr warns and falls back to latest without making a network request. |
MAIDR_CDN_TIMEOUT |
Seconds allowed for the version lookup, shared across attempts (default 3). Values of 0 or less fall back to the default, and anything above 30 is clamped to it with a warning — the units are seconds, so a value like 3000 is treated as a mistake rather than a request to wait fifty minutes. |
MAIDR_BUNDLE_STALE_WARNING |
Set to 0 to silence the stale-bundle warning. |
Keyboard Shortcuts and Controls
To interact with the plots using maidr, follow these steps:
- Press the Tab key to focus on the plot element.
- Use the arrow keys to move around the plot.
- Press B to toggle Braille mode.
- Press T to toggle Text mode.
- Press S to toggle Sonification (tones) mode.
- 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 z axis of current plot | l z | l z |
| 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 (/) |
Braille Generation
maidr incorporates a Braille mode that represents the plot using Braille symbols. This allows users with visual impairments to explore and interact with the plot using a refreshable Braille display. To achieve this, our system translates the plot’s visual elements and data points into a corresponding tactile representation using Braille patterns. For different plot types, such as barplot, boxplot, heatmap, and scatterplot, maidr employs unique encoding strategies tailored to effectively convey the data distribution, patterns, and trends. These tactile encodings range from using distinct Braille characters to represent value ranges, to employing characters that visually resemble the corresponding sections of a plot. By providing a comprehensive Braille representation for various plot types, maidr enables users with visual impairments to gain a deeper understanding of the underlying data and its insights.
Bar Plot
In the Braille representation of a barplot, data values are encoded as Braille characters based on their relative magnitude within the plot. Low values are denoted by Braille characters that have dots only along the bottom, while high values are indicated by characters that have dots along the top. Given the four height levels of Braille, the encoding is as follows:
- ⣀ represents values 0 to 25%
- ⠤ represents the 25% to 50%
- ⠒ represents the 50% to 75%
- ⠉ represents the 75% to 100%
This tactile encoding allows users to easily differentiate between the various value ranges in the barplot, facilitating their understanding of the data distribution and its underlying trends.
Histogram
The braille representation of a histogram is the same as that of a barplot.
Line Plot
In the Braille representation of a lineplot, braille is nearly identical to the above barplot: data values are encoded as Braille characters based on their relative magnitude within the plot. Low values are denoted by Braille characters that have dots only along the bottom, while high values are indicated by characters that have dots higher up.
Heatmap
In the Braille representation of a heatmap, values are depicted based on their relative magnitude within the plot, much like the approach used for barplots and scatterplots. Low values are denoted by Braille characters with dots only along the bottom, high values are represented by characters filled with dots, and blank or null values are indicated by empty spaces. With three height levels of Braille, the encoding is as follows:
- ⠤ represents values from 0% to 33%
- ⠒ represents values from 33% to 66%
- ⠉ represents values from 66% to 100%
- “⠀” (braille space) represents null or empty values
- “⢳” represents a row separator
Box Plot
The Braille representation of a boxplot employs Braille characters that visually resemble the corresponding sections of the boxplot. An example of such braille may look like ⠂ ⠒⠒⠒⠒⠒⠒⠿⠸⠿⠒ . The size of each section is denoted by the number of Braille characters used. The sections are encoded as follows:
- ⠂ represents lower outlier and upper outlier(s)
- ⠒ represents the left or right whiskers
- ⠿ represents the second or third quartiles
- ⠸⠇ represents the 50% midpoint (median)
- blank spaces represent empty spaces
We also impose some overarching rules:
- Each section must be represented with at least 1 braille character, assuming they have some positive length.
- Differences or equalities in whiskers and quartiles must be upheld. That is, if the min and max whisker are of equal length, they must have the same number of braille characters, or if they’re different, the number of characters must be different.
- Zero length sections, such as outliers and the median, are always represented by a set character. ⠂ in the case of outliers, ⠸⠇ in the case of the median.
This tactile encoding enables users to discern the various components of the boxplot, allowing them to comprehend the data distribution, detect outliers, and identify central tendencies and dispersion within the dataset.
To generate the braille, we use an algorithm that generates a distribution of characters based on a given proportional distribution and a specified total number of characters in the user’s braille display. This can be described mathematically as follows:
\[ c_i = \text{round}(n \cdot p_i), \text{ for } i = 1, 2, 3, \ldots, k \]
\[ c_i = \text{round}((n - C) \cdot p_i), \text{ for } i = 1, 2, 3, \ldots, k \]
Where
- n: Total number of characters (integer)
- C: Total number of length 0 characters to offset the total characters (outliers and median) (integer)
- p_i: Proportional distribution of each category i, where i ∈ {1, 2, 3, …, k} (real numbers, 0 ≤ p_i ≤ 1, and the sum of all p_i equals 1)
- c_i: Number of characters for each category i (integer)
The process is as follows in the code:
- We first convert our data set for a particular boxplot to an array of lengths.
- We then assign the single required character to each section.
- We also note connected sections, such as min and max.
- We then normalize and allocate all remaining characters according to their proportional distribution, making sure to add extra characters where needed to keep differences or equalities.
As an example, consider a boxplot with the following distribution: [10, 0, 20, 40, 30, 0, 30, 60, 50, 30, 0, 10, 0], with types [blank space, outlier, larger blank space, large min whisker, moderate sized lower quartile, the median, moderate sized upper quartile, another larger max whisker, a large blank space, an outlier, a small blank space, then another outlier], and a braille display length of 33. We would produce braille that looks like so:
⠂ ⠒⠒⠒⠒⠿⠿⠿⠸⠇⠿⠿⠿⠒⠒⠒⠒⠒⠒ ⠂ ⠂
Scatter Plot
- Note: The line layer in py maidr has not been implemented yet. The following is a placeholder for the future implementation.
In the Braille representation of a scatterplot, the encoding is performed only for the line layer (layer 2). The method is similar to that used for barplots, wherein data values are represented as Braille characters based on their relative magnitude within the plot. Low values are denoted by dots along the bottom, while high values are indicated by dots along the top. With four height levels of Braille, the encoding is as follows:
- ⣀ represents values from 0% to 25%
- ⠤ represents values from 25% to 50%
- ⠒ represents values from 50% to 75%
- ⠉ represents values from 75% to 100%
Segmented Bar Plots
- Note: The segmented bar plot in py maidr has not been implemented yet. The following is a placeholder for the future implementation.
Stacked bar, dodged bar, and normalized stacked bar all share the same system:
In the braille representation of segmented bar plots, braille depends on where you are. There are typically multiple levels to a segmented bar plot, and as you move (Up and Down arrow keys) between levels, the braille changes to represent your current level. At the top, there is also a Summary pseudo level of all levels added together, and a Combined pseudo level of each level separately.
- Regular level: Braille appears similar to a bar plot, with braille values corresponding to the magnitude of the level’s value for this point.
- Summary level: Same as regular level, but values now reflect the combined magnitude of all levels’ values for this point.
- Combined level: Similar to heatmap, where there are groups of magnitudes for each point separated by a ⢳ character. The first group has braille characters for each level for the first point, then a separator, then the second group has braille characters for each level in the second point, then a separator, and so on.
Getting Refreshable Braille Display Loaner
If you are a blind user and do not have a refreshable Braille display, you can request a loaner from the National Library Service (NLS) for the Blind and Print Disabled. Please follow our instruction on how to request an NLS eReader Braille Display.
Instruction on How to Verify and Use the AI Feature in py-maidr
We provide AI API keys only to alpha testers who have shared their email addresses through our survey form. If you are not an alpha tester, you can still use the AI feature by manually providing your own AI API keys in the Help menu.
For Alpha Testers
Activate the maidr plot by pressing the Tab key or clicking on the plot area.
In the interactive plot area, press H to open the Help menu.
Locate the text field labeled “Enter your email address”.
Type your email address in the text field. Note: The email address must match the one you provided in the survey form.
Press Enter to submit your email address.
Wait for the confirmation message to appear on the screen.
Press Enter to close the confirmation message.
Select up to two AI models from the checkboxes. Supported models include:
- OpenAI GPT-4o
- Google Gemini 2.0 Flash Experimental
- Anthropic Claude 3.5 Sonnet
- Note: All provided models are the latest versions.
Click the Save and Close button.
Check your email inbox for a verification email from
maidr.ai.Open the verification email and click on the verification link.
Once verified, return to the interactive plot area and press Ctrl+Shift+/ (forward slash) or Alt+Shift+/ (on Mac) to open the AI modal. You can now chat with the selected AI models about your plot.
- Note: The AI Chat modal is togglable. Use the same key combination to switch between the plot and the AI Chat modal.
For All Other Users
You can manually provide your own AI API keys in the Help menu. These keys are not saved and are only used for the current session. This means you will need to re-enter your API keys each time you open the app.
Activate the maidr plot by pressing the Tab key or clicking on the plot area.
In the interactive plot area, press H to open the Help menu.
Select up to two AI models from the checkboxes. Supported models include:
- OpenAI GPT-4o
- Google Gemini 2.0 Flash Experimental
- Anthropic Claude 3.5 Sonnet
- Note: All provided models are the latest versions.
Enter your API keys in the respective text fields.
Click the Save and Close button.
Return to the interactive plot area and press Ctrl+Shift+/ (forward slash) or Alt+Shift+/ (on Mac) to open the AI modal. You can now chat with the selected AI models about your plot.
- Note: The AI Chat modal is togglable. Use the same key combination to switch between the plot and the AI Chat modal.
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.
Code of Conduct
Please note that the maidr project is released with a contributor code of conduct.
By participating in this project you agree to abide by its terms.
📄 License
maidr is licensed under the GPL3 license.
🏛️ Governance
This project is primarily maintained by JooYoung Seo and Saairam Venkatesh. Other authors may occasionally assist with some of these duties.