Process and convert between different AAC file formats
Project description
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
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file aac_processors-0.1.8.tar.gz.
File metadata
- Download URL: aac_processors-0.1.8.tar.gz
- Upload date:
- Size: 22.2 MB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.12.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a9f848433db34667b0e7160896bcb41d42d29c8b11f48964253bc67691b955e6
|
|
| MD5 |
9a80dc6d76253543c90f80e0297c7539
|
|
| BLAKE2b-256 |
559483d2cdebcdaa4f30eb6c7c107656f3de2ce754474e1aeab6783c124037e6
|
Provenance
The following attestation bundles were made for aac_processors-0.1.8.tar.gz:
Publisher:
publish.yml on willwade/AACProcessors
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
aac_processors-0.1.8.tar.gz -
Subject digest:
a9f848433db34667b0e7160896bcb41d42d29c8b11f48964253bc67691b955e6 - Sigstore transparency entry: 188600859
- Sigstore integration time:
-
Permalink:
willwade/AACProcessors@afd542998784ee75d472ae98118abfec47f73532 -
Branch / Tag:
refs/tags/0.1.8 - Owner: https://github.com/willwade
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@afd542998784ee75d472ae98118abfec47f73532 -
Trigger Event:
release
-
Statement type:
File details
Details for the file aac_processors-0.1.8-py3-none-any.whl.
File metadata
- Download URL: aac_processors-0.1.8-py3-none-any.whl
- Upload date:
- Size: 73.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.12.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
60b8f1e48c132ecff069af9a157e90d3d3f383a224846dcf9358536384701067
|
|
| MD5 |
8cc40ccafc9cc3e82c74980607762eaf
|
|
| BLAKE2b-256 |
57a9cd3c550ba306144399b93730c15c2a2235acec74db6ad19bb481cdd49eb3
|
Provenance
The following attestation bundles were made for aac_processors-0.1.8-py3-none-any.whl:
Publisher:
publish.yml on willwade/AACProcessors
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
aac_processors-0.1.8-py3-none-any.whl -
Subject digest:
60b8f1e48c132ecff069af9a157e90d3d3f383a224846dcf9358536384701067 - Sigstore transparency entry: 188600860
- Sigstore integration time:
-
Permalink:
willwade/AACProcessors@afd542998784ee75d472ae98118abfec47f73532 -
Branch / Tag:
refs/tags/0.1.8 - Owner: https://github.com/willwade
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@afd542998784ee75d472ae98118abfec47f73532 -
Trigger Event:
release
-
Statement type: