| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
| Name | Name | Last commit date | ||
|---|---|---|---|---|
A screen-reader-first mathematical accessibility toolkit for converting LaTeX, MathML, and plaintext/Unicode math into speech, Braille, and navigable ARIA structures.
Quick Start • Features • Installation • Usage • API Reference • Contributing
Accessible Math Reader (AMR) is a Python package and web application that makes mathematical notation accessible to visually impaired users. It parses LaTeX, MathML, and plaintext/Unicode math expressions and converts them into:
AMR can be used as a Python library, a CLI tool, or through a Flask-based web interface.
🎓 Developed at FCRIT Vashi as a project in academic research in accessibility and inclusive technology.
| Category | Highlights |
|---|---|
| Multi-Format Input | Parse LaTeX, MathML, and plaintext/Unicode math expressions with auto-detection |
| Speech Output | Natural language descriptions with 3 verbosity levels and SSML support |
| ⠿ Braille Support | Full Nemeth Braille Code and Unified English Braille (UEB) converters |
| ARIA Navigation | Keyboard-accessible, step-by-step expression exploration with 3 navigation modes |
| Multi-Format Clipboard | Copy formulas as LaTeX, accessible text, or Braille from the web UI |
| Accessible Web UI | Dark/light themes, high-contrast mode, zoom controls, screen-reader optimized |
| Plugin System | Extensible architecture for custom speech rules, Braille notations, and input formats |
| CLI Tool | Full-featured command-line interface with interactive and batch modes |
┌─────────────────────────────────────────────────────────────────────┐
│ Accessible Math Reader │
├──────────┬──────────┬───────────────────────────────┬───────────────┤
│ CLI │ Web UI │ Python API (MathReader) │ Plugins │
│ (amr) │ (Flask) │ │ (extensible) │
├──────────┴──────────┴───────────────────────────────┴───────────────┤
│ Core Pipeline │
│ ┌──────────┐ ┌──────────────┐ ┌────────────────────────────┐ │
│ │ Parser │──▸│ Semantic AST │──▸│ Renderers │ │
│ │ LaTeX │ │ (SemanticNode│ │ ┌─────────┬────────────┐ │ │
│ │ MathML │ │ NodeType) │ │ │ Speech │ Braille │ │ │
│ │ Plaintext│ | | | | | | | |
│ └──────────┘ └──────┬───────┘ │ │ Engine │ Nemeth/UEB │ │ │
│ │ │ └─────────┴────────────┘ │ │
│ ▼ │ ┌─────────┬────────────┐ │ │
│ ┌───────────┐ │ │ ARIA │ Simple │ │ │
│ │ Navigator │ │ │Renderer │ Text │ │ │
│ │ (keyboard │ │ └─────────┴────────────┘ │ │
│ │ explore) │ └────────────────────────────┘ │
│ └───────────┘ │
├─────────────────────────────────────────────────────────────────────┤
│ Configuration │
│ Config · SpeechConfig · BrailleConfig · A11yConfig │
└─────────────────────────────────────────────────────────────────────┘
accessible-math-reader/ ├── accessible_math_reader/ # 📦 Installable Python package │ ├── __init__.py # Public API exports │ ├── reader.py # MathReader — high-level unified interface │ ├── server.py # WSGI entry point for production deployment │ ├── cli.py # CLI entry point (`amr` command) │ ├── config.py # Configuration management (env, file, API) │ ├── core/ # Core parsing & rendering engine │ │ ├── parser.py # LaTeX / MathML / Plaintext → Semantic AST │ │ ├── semantic.py # SemanticNode, NodeType, MathNavigator │ │ ├── renderer.py # Base rendering infrastructure │ │ ├── aria_navigator.py # ARIA-enhanced keyboard navigation │ │ ├── aria_renderer.py # Accessible HTML generation │ │ └── accessibility_contract.py # Accessibility validation contracts │ ├── speech/ # Speech output subsystem │ │ ├── engine.py # TTS engine abstraction (gTTS backend) │ │ └── rules.py # Verbosity-based speech rules │ ├── braille/ # Braille conversion subsystem │ │ ├── nemeth.py # Nemeth Braille Code converter │ │ └── ueb.py # Unified English Braille converter │ └── plugins/ # Plugin system │ └── base.py # Abstract plugin base classes ├── app.py # 🌐 Flask web application (dev entry point) ├── templates/ │ └── index.html # 🖥️ Web UI template (dark/light, accessible) ├── static/ │ ├── css/style.css # Web UI styles │ └── js/ │ ├── app.js # Frontend logic & keyboard shortcuts │ └── clipboard.js # Multi-format clipboard support ├── docs/ # 📚 Documentation │ ├── api.md # Full Python API reference │ ├── input-formats.md # Supported LaTeX & MathML syntax │ ├── accessibility.md # Screen reader, Braille & ARIA guide │ ├── configuration.md # Configuration reference │ └── examples.md # Code samples & use cases ├── CHANGELOG.md # Version history and migration notes ├── pyproject.toml # Package metadata & build config ├── requirements.txt # Web-app-specific dependencies └── LICENSE # MIT License
Install directly from the repository:
pip install accessible-math-reader# Clone the repository
git clone https://github.com/AndyFerns/Accessible-Math-Reader.git
cd Accessible-Math-Reader
# Create and activate a virtual environment
python -m venv venv
# Windows
venv\Scripts\activate
# Linux / macOS
source venv/bin/activate
# Install the package in editable mode (with all extras)
pip install -e ".[dev,web]"This installs AMR as a package and registers the amr CLI command.
If you only need the Python API (no web UI, no dev tools):
pip install -e .Core dependencies are just gtts and lxml.
AMR provides three interfaces: a Python API, a CLI tool, and a web UI.
from accessible_math_reader import MathReader
reader = MathReader()
# ── Speech ──────────────────────────────────────────
speech = reader.to_speech(r"\frac{a}{b}")
print(speech)
# → "start fraction a over b end fraction"
# ── Braille (Nemeth) ────────────────────────────────
braille = reader.to_braille(r"\frac{a}{b}", notation="nemeth")
print(braille)
# → "⠹⠁⠌⠃⠼"
# ── Braille (UEB) ──────────────────────────────────
ueb = reader.to_braille(r"\frac{a}{b}", notation="ueb")
# ── Audio file ──────────────────────────────────────
reader.to_audio(r"\frac{a}{b}", "output.mp3")
# ── SSML markup ─────────────────────────────────────
ssml = reader.to_ssml(r"\sqrt{x}")
# ── Semantic tree inspection ────────────────────────
structure = reader.parse(r"\frac{a+b}{c}")
# ── Plaintext / Unicode math ────────────────────────
speech = reader.to_speech("x² + y² = z²")
speech = reader.to_speech("(a+b)/(c-d)")
speech = reader.to_speech("sqrt(x) + π")from accessible_math_reader import MathReader, VerbosityLevel
reader = MathReader()
reader.set_verbosity(VerbosityLevel.VERBOSE)
reader.to_speech(r"\frac{a}{b}") # "start fraction a over b end fraction"
reader.set_verbosity(VerbosityLevel.CONCISE)
reader.to_speech(r"\frac{a}{b}") # "a over b"
reader.set_verbosity(VerbosityLevel.SUPERBRIEF)
reader.to_speech(r"\frac{a}{b}") # "fraction a b"from accessible_math_reader import MathReader, Config
from accessible_math_reader.config import SpeechConfig, BrailleConfig, SpeechStyle, BrailleNotation
config = Config(
speech=SpeechConfig(style=SpeechStyle.CONCISE, language="en", rate=0.9),
braille=BrailleConfig(notation=BrailleNotation.UEB),
)
reader = MathReader(config)nav = reader.get_navigator(r"\frac{a+b}{c}")
nav.enter() # Drill into the fraction
nav.next() # Move to the next sibling
nav.exit() # Go back up to the parent
path = nav.get_path() # Breadcrumb trail from rootAfter installing the package, the amr command is available system-wide.
# Speech output (default)
amr "\frac{a^2 + b^2}{c}"
# Plaintext / Unicode math
amr "x² + y² = z²"
amr "(a+b)/(c-d)"
amr "sqrt(x) + π"
# Braille output (Nemeth)
amr --braille "\frac{a}{b}"
# Braille output (UEB)
amr --braille --notation ueb "\sqrt{x}"
# Generate audio file
amr --audio output.mp3 "\frac{1}{2}"
# SSML output
amr --ssml "\frac{a}{b}"
# JSON output (speech + braille + structure)
amr --json "\frac{a}{b}"
# Show expression tree structure
amr --structure "\frac{a+b}{c}"
# Set verbosity
amr --verbosity concise "x^2 + y^2 = z^2"
# Read from file (one expression per line)
amr --input equations.txt
# Write output to file
amr --output results.txt "\frac{a}{b}"
# Interactive REPL mode
amr --interactive| Command | Action |
|---|---|
| :quit / :exit | Exit interactive mode |
| :verbosity <level> | Set verbosity (verbose, concise, superbrief) |
| :braille | Switch to Braille output |
| :speech | Switch to speech output |
| :help | Show all commands |
The web UI provides a visual, accessible interface built with Flask:
# Install web dependencies
pip install -e ".[web]"
# Development mode (with auto-reload)
python app.py
# Open http://localhost:5000
# Production mode (via the unified WSGI server)
python -m accessible_math_reader.server
# Open http://localhost:5000
# Production with Gunicorn (Linux/macOS)
gunicorn "accessible_math_reader.server:create_app()" -b 0.0.0.0:8000
# Production with Waitress (Windows)
waitress-serve --port=8000 --call accessible_math_reader.server:create_appWeb UI Features:
AMR supports three configuration methods (highest priority first):
# Linux / macOS
export AMR_SPEECH_STYLE=concise # verbose | concise | superbrief
export AMR_BRAILLE_NOTATION=nemeth # nemeth | ueb
export AMR_SPEECH_LANGUAGE=en # Language code
export AMR_PLUGIN_DIRS=/path/to/plugins
# Windows PowerShell
$env:AMR_SPEECH_STYLE = "concise"
$env:AMR_BRAILLE_NOTATION = "ueb"{
"speech": {
"style": "verbose",
"language": "en",
"rate": 1.0,
"announce_structure": true
},
"braille": {
"notation": "nemeth",
"include_indicators": true
},
"accessibility": {
"step_by_step": true,
"announce_errors": true,
"highlight_current": true
}
}config = Config.from_file("amr-config.json")
reader = MathReader(config)config = Config()
config.speech.style = SpeechStyle.CONCISE
config.save("my-config.json")📖 Full configuration reference: docs/configuration.md
AMR's plugin architecture supports four extension points:
| Plugin Type | Base Class | Purpose |
|---|---|---|
| Speech Rules | SpeechRulesPlugin | Custom verbalization rules for math constructs |
| Braille Notation | BrailleNotationPlugin | Additional Braille systems (French, German, etc.) |
| Input Format | InputFormatPlugin | New input parsers (AsciiMath, MathJSON, etc.) |
| Localization | BasePlugin | Language/locale-specific adaptations |
from accessible_math_reader.plugins.base import SpeechRulesPlugin, PluginInfo, PluginType
class MyCustomRules(SpeechRulesPlugin):
@property
def info(self):
return PluginInfo(
name="my-rules",
version="1.0.0",
description="Custom speech rules",
author="Your Name",
plugin_type=PluginType.SPEECH_RULES,
)
def get_speech_rules(self):
return {"FRACTION": lambda node: "custom fraction rendering"}| Document | Description |
|---|---|
| API Reference | Full Python API with code examples |
| Input Formats | Supported LaTeX commands and MathML elements |
| Accessibility Guide | Screen reader, Braille display, and ARIA features |
| Configuration | All speech, Braille, and accessibility settings |
| Examples | Common use cases, batch processing, and web integration |
This project uses MkDocs with the Material theme for documentation hosting:
# Install documentation dependencies
pip install mkdocs mkdocs-material mkdocstrings[python]
# Serve docs locally (live reload)
mkdocs serve
# Build static site
mkdocs buildSee mkdocs.yml for the full configuration.
| Standard | Status |
|---|---|
| WCAG 2.2 AA | ✅ Full compliance for web interface |
| WAI-ARIA 1.2 | ✅ Proper roles, labels, live regions, roving tabindex |
| Screen Readers | ✅ Tested with NVDA, JAWS, VoiceOver, Narrator |
| Keyboard Navigation | ✅ Full keyboard access, visible focus indicators |
| Braille Displays | ✅ Unicode Braille output compatible with refreshable displays |
git clone https://github.com/AndyFerns/Accessible-Math-Reader.git
cd Accessible-Math-Reader
python -m venv venv
venv\Scripts\activate # Windows
# source venv/bin/activate # Linux / macOS
pip install -e ".[dev,web]"# Run full test suite with coverage
pytest tests/ -v --cov=accessible_math_reader --cov-report=term-missing
# Run a specific test file
pytest tests/test_parser.py -v# Run ruff linter
ruff check accessible_math_reader/
# Auto-fix lint issues
ruff check accessible_math_reader/ --fix# Development mode (with auto-reload on http://localhost:5000)
python app.py
# Production mode (unified WSGI server on http://localhost:5000)
python -m accessible_math_reader.serverWe welcome contributions! Here's how to get started:
# Install build tool
pip install build
# Build source distribution and wheel
python -m build
# Output will be in dist/
# dist/accessible_math_reader-0.5.2.tar.gz
# dist/accessible_math_reader-0.5.2-py3-none-any.whl# Install twine
pip install twine
# Upload to TestPyPI (for testing)
twine upload --repository testpypi dist/*
# Upload to PyPI (production)
twine upload dist/*# From the wheel file
pip install dist/accessible_math_reader-0.1.0-py3-none-any.whl
# From TestPyPI
pip install --index-url https://test.pypi.org/simple/ accessible-math-reader
# From PyPI (once published)
pip install accessible-math-readerThis project is licensed under the MIT License — see the LICENSE file for details.
Built with ♿ accessibility as a first-class priority.
| Back | FazBrowse Home | New Git URL |