AACProcessors
A Python library to read, import, export and modify pagesets from different AAC (Augmentative and Alternative Communication) providers. Currently supports:
- Grid 3 (
.gridset) - CoughDrop (OpenBoard) (
.obf,.obz) - TouchChat (
.touchChat) - Snap Core First (
.spb)
And unusual formats:
- Dot Processor (.dot)
- OPML (.opml)
- Apple Panels
- Screenshot Processor (optional)
Features
- Extract text content from AAC pagesets
- Load AAC pagesets into a common tree structure
- Support for multiple AAC software formats
- Translation support for extracted text
- Consistent API across different AAC formats
- Convert between different AAC formats
- Analyze vocabulary usage and structure
Installation
pip install aac-processors
Quick Start
from aac_processors import GridsetProcessor, CoughDropProcessor, TouchChatProcessor, SnapProcessor
# Example with Grid 3
processor = GridsetProcessor()
texts = processor.extract_texts("path/to/your.gridset")
print(f"Found {len(texts)} text items")
# Load into tree structure
tree = processor.load_into_tree("path/to/your.gridset")
print(f"Found {len(tree.pages)} pages")
# Translate texts
translations = {
"Hello": "Hola",
"Goodbye": "Adiós"
}
translated_file = processor.process_texts("path/to/your.gridset", translations, "path/to/output.gridset")
Try it now!
Want to try AACProcessors without installing? Click below to run our interactive demo:
This interactive notebook will:
- Install AACProcessors
- Download example AAC files
- Demonstrate key features:
- Viewing file structures
- Extracting texts
- Analyzing vocabulary
- Converting between formats
Usage Examples
Converting Between Formats (OBZ Import/Export)
from aac_processors import GridsetProcessor, CoughDropProcessor
# Convert Grid3 to CoughDrop OBZ
grid_processor = GridsetProcessor()
cough_processor = CoughDropProcessor()
# Load Grid3 file into common tree structure
tree = grid_processor.load_into_tree("path/to/your.gridset")
# Export tree to CoughDrop OBZ format
cough_processor.export_tree(tree, "output.obz")
# Import from OBZ
imported_tree = cough_processor.load_into_tree("path/to/board.obz")
Viewing File Structure
The library includes two ways to view AAC board structures:
- Using the command-line viewer:
# Using the standalone viewer script
python demo_viewer.py path/to/your/board.gridset
# Or using the package module directly
python -m aac_processors.viewer path/to/your/board.gridset
# Programmatically:
from aac_processors import viewer, GridsetProcessor
# Load and print a board structure
processor = GridsetProcessor()
tree = processor.load_into_tree("path/to/your.gridset")
viewer.print_tree(tree)
# Or use the auto-detection feature
viewer.main() # Will prompt for file path
- Programmatically:
from aac_processors import viewer, GridsetProcessor
from aac_processors.tree_structure import ButtonType
# Load and print a board structure
processor = GridsetProcessor()
tree = processor.load_into_tree("path/to/your.gridset")
viewer.print_tree(tree)
# Or use the auto-detection feature
viewer.main() # Will prompt for file path
The viewer will show:
- Complete board structure with pages and buttons
- Button types (🗣️ Speech, 🔀 Navigation, ⚡ Action)
- Grid layout and button positions
- Navigation analysis (dead ends, orphaned pages)
- Circular references in navigation
Vocabulary Analysis
from aac_processors import GridsetProcessor
from collections import Counter
import re
def analyze_vocabulary(file_path):
processor = GridsetProcessor()
tree = processor.load_into_tree(file_path)
# Collect all text from buttons
words = []
for page in tree.pages.values():
for button in page.buttons:
if button.label:
# Split into words and clean
button_words = re.findall(r'\w+', button.label.lower())
words.extend(button_words)
if button.message:
message_words = re.findall(r'\w+', button.message.lower())
words.extend(message_words)
# Count word frequencies
word_counts = Counter(words)
# Print statistics
print(f"Total unique words: {len(word_counts)}")
print("\nMost common words:")
for word, count in word_counts.most_common(10):
print(f" {word}: {count}")
return word_counts
# Example usage
vocabulary = analyze_vocabulary("path/to/your.gridset")
Demo
See demo.py for a complete example of how to use the library.
python demo.py
Output:
=== Viewing File Structure ===
Viewing structure of SimpleTest.gridset:
=== AAC Board Structure ===
Root Page:
📄 Start (4x4 grid)
Row 0:
[Empty] (0, 0)
🔀 quick chat (0, 1)
└─ Says: quick chat
└─ Goes to: quick chat
🔀 don't like (0, 2)
└─ Says: don't like
└─ Goes to: Don't like
🔀 something different (0, 3)
└─ Says: something different
└─ Goes to: something different
Row 1:
[Empty] (1, 0)
🔀 something's wrong (1, 1)
└─ Says: something's wrong
└─ Goes to: something's wrong
🔀 I want (1, 2)
└─ Says: I want
└─ Goes to: I want
🔀 Comment (1, 3)
└─ Says: Comment
└─ Goes to: Comment
Row 2:
[Empty] (2, 0)
🔀 About me (2, 1)
└─ Says: About me
└─ Goes to: About me
└─ Target Page:
📄 About me (5x4 grid)
Row 0:
🗣️ [No Label] (0, 0)
🗣️ Back (0, 1)
└─ Says: Back
🔀 Family (0, 2)
└─ Says: Family
└─ Goes to: Family
└─ Target Page:
📄 Family (5x7 grid)
Row 0:
[Empty] (0, 0)
🗣️ Back (0, 1)
└─ Says: Back
[Empty] (0, 2)
🗣️ Younger Sister (0, 3)
└─ Says: Younger Sister
[Empty] (0, 4)
[Empty] (0, 5)
[Empty] (0, 6)
Row 1:
[Empty] (1, 0)
🗣️ Dad (1, 1)
└─ Says: Dad
[Empty] (1, 2)
[Empty] (1, 3)
[Empty] (1, 4)
[Empty] (1, 5)
[Empty] (1, 6)
Row 2:
[Empty] (2, 0)
[Empty] (2, 1)
[Empty] (2, 2)
🔀 Cousins (2, 3)
└─ Says: Cousins
└─ Goes to: Cousins
[Empty] (2, 4)
[Empty] (2, 5)
[Empty] (2, 6)
Row 3:
[Empty] (3, 0)
🗣️ Mum (3, 1)
└─ Says: Mum
[Empty] (3, 2)
[Empty] (3, 3)
[Empty] (3, 4)
[Empty] (3, 5)
[Empty] (3, 6)
Row 4:
[Empty] (4, 0)
[Empty] (4, 1)
[Empty] (4, 2)
🔀 Aunts and Uncles (4, 3)
└─ Says: Aunts and Uncles
└─ Goes to: Aunts and Uncles
[Empty] (4, 4)
[Empty] (4, 5)
[Empty] (4, 6)
🗣️ Vegetarian (0, 3)
└─ Says: Vegetarian
Row 1:
[Empty] (1, 0)
🗣️ Name (1, 1)
└─ Says: Name
🔀 Pets (1, 2)
└─ Says: Pets
└─ Goes to: Pets
[Empty] (1, 3)
Row 2:
[Empty] (2, 0)
🗣️ Age (2, 1)
└─ Says: Age
🔀 Places I have been (2, 2)
└─ Says: Places I have been
└─ Goes to: Places I have been
[Empty] (2, 3)
Row 3:
[Empty] (3, 0)
🗣️ My birthday (3, 1)
└─ Says: My birthday
🗣️ like to look (3, 2)
└─ Says: like to look
[Empty] (3, 3)
Row 4:
[Empty] (4, 0)
[Empty] (4, 1)
[Empty] (4, 2)
[Empty] (4, 3)
🔀 I'm asking a question (2, 2)
└─ Says: I'm asking a question
└─ Goes to: questions
🔀 I feel (2, 3)
└─ Says: I feel
└─ Goes to: Feelings
└─ Target Page:
📄 Feelings (6x4 grid)
Row 0:
🗣️ [No Label] (0, 0)
🗣️ Back (0, 1)
└─ Says: Back
🗣️ angry. (0, 2)
└─ Says: angry.
[Empty] (0, 3)
Row 1:
[Empty] (1, 0)
🗣️ happy. (1, 1)
└─ Says: happy.
🗣️ excited. (1, 2)
└─ Says: excited.
[Empty] (1, 3)
Row 2:
[Empty] (2, 0)
🗣️ sad. (2, 1)
└─ Says: sad.
🗣️ fantastic. (2, 2)
└─ Says: fantastic.
[Empty] (2, 3)
Row 3:
[Empty] (3, 0)
🗣️ tired. (3, 1)
└─ Says: tired.
[Empty] (3, 2)
[Empty] (3, 3)
Row 4:
[Empty] (4, 0)
[Empty] (4, 1)
[Empty] (4, 2)
[Empty] (4, 3)
Row 5:
[Empty] (5, 0)
[Empty] (5, 1)
[Empty] (5, 2)
[Empty] (5, 3)
Row 3:
[Empty] (3, 0)
🔀 like (3, 1)
└─ Says: like
└─ Goes to: Like
🔀 Places to go (3, 2)
└─ Says: Places to go
└─ Goes to: let's go
🔀 Alphabet (3, 3)
└─ Says: Alphabet
└─ Goes to: Alphabet
=== Navigation Analysis ===
Total Pages: 6
Dead End Pages (no way back):
- Family
- Feelings
Orphaned Pages (no way to reach):
- Drinks
- About me 2
=== Extracting Texts ===
Extracted 43 texts from SimpleTest.gridset
Sample texts: ["something's wrong", 'Age', 'Back to home page', 'I feel', 'Pets']
=== Loading Tree Structure ===
Loaded 6 pages from SimpleTest.gridset
Page Drinks: Drinks
Grid size: (5, 4)
Buttons: 7
Page Family: Family
Grid size: (5, 7)
Buttons: 8
Supported Formats
Grid 3 (.gridset)
- Full support for reading grid layouts
- Text extraction from buttons and pages
- Translation support
CoughDrop (.obf, .obz)
- Support for both single board (
.obf) and board set (.obz) formats - Extraction of button labels and messages
- Translation capabilities
TouchChat (.touchChat)
- Support for TouchChat page sets
- Button text extraction
- Page structure loading
Snap Core First (.spb)
- Support for Snap Core First board sets
- Text extraction from buttons and pages
- Basic translation support
Screenshot Processor (optional)
The screenshot processor is an optional dependency that requires additional dependencies. Install it with:
pip install aac-processors[screenshot]
screenshot Usage
from aac_processors import ScreenshotProcessor
# Create processor
processor = ScreenshotProcessor()
# Load and print a board structure from screenshot
tree = processor.load_into_tree(
"path/to/screenshot.png",
grid_rows=6, # Optional: specify grid dimensions if known
grid_cols=4 # e.g. 6x4 for TouchChat24, 6x10 for TouchChat60
)
viewer.print_tree(tree)
# Extract text from screenshot
texts = processor.extract_texts("path/to/screenshot.png")
print(texts)
# Initialize processor with debug images enabled (optional)
processor = ScreenshotProcessor(save_debug_images=True)
# Get detailed page info including colors and grid layout
page = processor.create_page_from_screenshot(
"path/to/screenshot.png",
grid_rows=6, # Number of rows if known
grid_cols=4, # Number of columns if known
ignore_rows=1, # Skip top N rows (e.g. for menu bars)
)
print(f"Grid size: {page.grid_size}")
for btn in page.buttons:
print(f"Button at {btn.position}: {btn.label} (color: {btn.style.body_color})")
Debug Images: When save_debug_images=True is set, the processor creates two visualization files alongside the input image:
input.png.debug.png: Shows the detected grid cells in greeninput.png.text_debug.png: Shows detected text regions in blue with text overlay
Command Line Interface
The package provides a command-line interface (CLI) for viewing and converting AAC files. After installation, you can use it in two ways:
Interactive Mode
Simply run without arguments to enter interactive mode:
aac-processors
This will guide you through:
- Selecting an AAC file (with tab completion)
- Choosing to view its structure or convert it
- If converting, selecting the target format and output path
Command Line Mode
For direct command-line usage:
- View an AAC file structure:
aac-processors view input.gridset
- Convert between formats:
# Basic conversion (auto-generates output filename)
aac-processors convert input.gridset --to coughdrop
# Specify custom output path
aac-processors convert input.obf --to grid --output custom_name.gridset
API Documentation
Base Classes
FileProcessor
The base class that all format-specific processors inherit from.
class FileProcessor:
def extract_texts(self, file_path: str) -> List[str]:
"""Extract all text content from the file"""
def load_into_tree(self, file_path: str) -> AACTree:
"""Load the file into a common tree structure"""
def process_texts(
self,
file_path: str,
translations: Optional[Dict[str, str]] = None,
output_path: Optional[str] = None
) -> Union[List[str], str, None]:
"""Process and translate texts in the file.
Returns:
- List[str] if extracting texts (translations=None)
- str if translating (path to translated file)
- None if error occurs
"""
def set_source_file(self, file_path: str) -> None:
"""Set the source file path for processing"""
def cleanup_temp_files(self) -> None:
"""Clean up any temporary files created during processing"""
Common Data Structures
AACTree
Represents the common structure for all AAC formats.
class AACTree:
pages: Dict[str, AACPage] # Dictionary of pages by ID
root_id: Optional[str] # ID of the root page
def add_page(self, page: AACPage) -> None:
"""Add a page to the tree"""
def get_page(self, page_id: str) -> Optional[AACPage]:
"""Get a page by ID"""
AACPage
Represents a single page in an AAC system.
class AACPage:
id: str # Unique identifier for the page
name: str # Display name of the page
grid_size: Tuple[int, int] # (rows, columns)
buttons: List[AACButton] # List of buttons on the page
AACButton
Represents a button in an AAC system.
class AACButton:
id: str # Unique identifier for the button
label: str # Display text
type: ButtonType # SPEAK, NAVIGATE, ACTION, etc.
position: Tuple[int, int] # Grid position (row, col)
vocalization: Optional[str] # Text to speak
target_page_id: Optional[str] # For navigation buttons
Contributing
Contributions are welcome! Please feel free to submit a Pull Request. For major changes, please open an issue first to discuss what you would like to change.
- Fork the repository
- Create your feature branch (
git checkout -b feature/AmazingFeature) - Commit your changes (
git commit -m 'Add some AmazingFeature') - Push to the branch (
git push origin feature/AmazingFeature) - Open a Pull Request
Testing
To run the tests:
python -m pytest
Current test coverage: 52%
Dev
uv pip install -e ".[dev,screenshot]"
License
This project is licensed under the AGPLv3 License - see the LICENSE file for details.
Acknowledgments
- OpenAAC
- The AAC community for their feedback and support
Contributors
Metadata
Release files for aac-processors 0.1.8
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| aac_processors-0.1.8.tar.gz | 22.2 MB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| aac_processors-0.1.8-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 22.3 MB
Release files / aac_processors-0.1.8.tar.gz
| Download URL | aac_processors-0.1.8.tar.gz |
|---|---|
| Size | 22.2 MB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
a9f848433db34667b0e7160896bcb41d42d29c8b11f48964253bc67691b955e6
|
|
BLAKE2b-256 checksum How to use checksums |
559483d2cdebcdaa4f30eb6c7c107656f3de2ce754474e1aeab6783c124037e6
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.12.9
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Mar 26, 2025.
Transparency logRelease files / aac_processors-0.1.8-py3-none-any.whl
| Download URL | aac_processors-0.1.8-py3-none-any.whl |
|---|---|
| Size | 73.9 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
60b8f1e48c132ecff069af9a157e90d3d3f383a224846dcf9358536384701067
|
|
BLAKE2b-256 checksum How to use checksums |
57a9cd3c550ba306144399b93730c15c2a2235acec74db6ad19bb481cdd49eb3
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.12.9
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Mar 26, 2025.
Transparency log