A PyQt6 desktop playground for exploring classic sorting algorithms through deterministic, step-by-step animation. Every frame comes from a concrete Step object emitted by the algorithm, making runs reproducible, exportable, and easy to replay for teaching or research.
Kapture.2025-11-02.at.11.45.57.mp4
- Single Visualizer: One tab per algorithm with synced HUD, narration, export tools, theme toggle, and keyboard/mouse controls. Manual input fields automatically apply values 1.5 seconds after you stop typing.
- Compare Mode (Fixed!): Launch a dual-pane workspace from the launcher to evaluate two algorithms side by side. Recent fixes ensure proper synchronization and stepping behavior between both panes.
- Deterministic algorithm engine: Bubble, Insertion, Selection, Heap, Shell, Merge (bottom-up), Quick (median-of-three), Cocktail, Counting, Radix (LSD), Bucket, Comb, and a Timsort trace all register through a plugin system and emit strongly typed
Steprecords. - Reproducible data presets: Generate random, nearly-sorted, reverse, reverse-run, few-unique, or already-sorted datasets with a visible seed so anyone can recreate a run exactly.
- Instrumented playback: Stepping, scrubbing, and timed playback all derive from the same checkpointed replay buffer. You can always step backward or jump to any frame without drift.
- Export & benchmark suite: Export traces to CSV/JSON/PNG/GIF and run a batch benchmark that sweeps algorithms against the active dataset configuration and writes a CSV report.
- Metrics Verification Tool: New
scripts/verify_metrics.pyallows offline verification of algorithm metrics including step counts, comparisons, swaps, and inversion counts. - Accessibility & persistence: Dark and high-contrast themes, tooltip theming, saved window geometry, FPS, presets, and the last custom array all round-trip through
QSettings. - Robust logging: A hardened
sys.excepthookwrites to a rotating log viaplatformdirs(if available) before surfacing runtime errors in the UI. - Comprehensive test suite: Over 30 test files covering UI components, algorithm correctness, keyboard shortcuts, replay determinism, export serialization, and property-based testing with Hypothesis.
- Python 3.10 or newer
- Qt runtime (bundled automatically via
PyQt6) - macOS, Windows, or Linux desktop environment
Clone the repository, then choose one of the following setup paths:
# macOS / Linux
./scripts/setup.sh:: Windows
scripts\setup.batBoth scripts create .venv/, activate it temporarily, and install requirements.txt.
Prefer manual setup? Run the equivalent commands yourself:
python -m venv .venv
source .venv/bin/activate # .venv\Scripts\activate on Windows
pip install -r requirements.txtFrom the project root, choose one of these methods:
Option A: Direct launch (requires manual venv activation)
python main.pyOption B: Automated launch script (handles venv and dependencies automatically)
# macOS / Linux
./scripts/run.sh
# Or use the Python version (cross-platform)
python scripts/run.pyThe automated scripts (run.sh and run.py) will create the virtual environment if needed, install/update dependencies, and launch the app—ideal for quick development.
You will land on the launcher window:
- Single Visualizer loads the production-ready tabbed workspace.
- Compare Mode opens a dual-pane view to compare different algorithms' runtimes against each other.
- Enter comma-separated integers in the input field (numbers are automatically applied 1.5 seconds after you stop typing) or click Generate to use the active preset/seed.
- Use Start, Step ▶, Step ◀, the timeline slider, or keyboard shortcuts to navigate. Every action replays the canonical
Stepsequence—no frame skipping. - Toggle Show values at small
nto annotate each bar. - Click Export to choose CSV, JSON, PNG, or GIF. PNG renders the current canvas. GIF synthesizes the animation from captured frames; you must play through the run first.
- Hit Benchmark to produce
benchmark.csvwith wall-clock timing for the active algorithm (three sequential seeds per preset, including any custom array). - The Details pane surfaces algorithm notes, complexity tables, and metadata pulled from the registry.
- Launch two algorithms side by side for direct comparison
- Synchronized playback controls affect both panes simultaneously
- Independent algorithm selection for each pane
- Shared dataset configuration ensures fair comparison
- Fixed stepping behavior ensures both algorithms advance in sync
- Perfect for teaching algorithm efficiency differences
- View → High Contrast Mode switches to a light theme
- View → Show Debug Panel reveals live internals (player state, timers, recent steps) for the active tab
- Auto-apply input with 1.5-second debouncing prevents accidental changes while typing
- Keyboard shortcuts for all major functions (Space for play/pause, Left/Right arrows for stepping, etc.)
| Algorithm | Category | Stable | In-place | Typical Complexity (best / avg / worst) | Notes |
|---|---|---|---|---|---|
| Bubble Sort | Comparison | ✓ | ✓ | O(n) / O(n²) / O(n²) | Early exit once no swaps occur; ideal baseline for demos. |
| Insertion Sort | Comparison | ✓ | ✓ | O(n) / O(n²) / O(n²) | Highlights key vs. shift operations with distinct colors. |
| Selection Sort | Comparison | ✗ | ✓ | O(n²) / O(n²) / O(n²) | Emits compare/swap pairs to visualize the selection process. |
| Heap Sort | Comparison | ✗ | ✓ | O(n log n) | Instrumented heapify and pop phases with pivot highlights. |
| Shell Sort | Comparison | ✗ | ✓ | O(n log n) average | Uses Pratt-inspired gap sequence; shows gap comparisons distinctly. |
| Merge Sort (BU) | Comparison | ✓ | ✗ | O(n log n) | Bottom-up merges with violet merge markers and auxiliary array snapshots. |
| Quick Sort | Comparison | ✗ | ✓ | O(n log n) / O(n log n) / O(n²) | Median-of-three pivot selection with pivot/bounds instrumentation. |
| Cocktail Shaker | Comparison | ✓ | ✓ | O(n) / O(n²) / O(n²) | Bi-directional pass emphasizes swap direction changes. |
| Comb Sort | Comparison | ✗ | ✓ | O(n log n) average | Gap shrink factor 1.3 with final bubble clean-up. |
| Counting Sort | Non-comparison | ✓ | ✗ | O(n + k) | Tracks histogram, prefix sums, and stable placements. |
| Radix Sort (LSD) | Non-comparison | ✓ | ✗ | O(d (n + k)) | Offsets negatives once then streams digit passes through Counting Sort. |
| Bucket Sort | Non-comparison | ✓ | ✗ | O(n) average / O(n²) worst | Normalizes values into buckets and sorts each with Python's Timsort. |
| Timsort Trace | Hybrid | ✓ | ✗ | O(n) / O(n log n) / O(n log n) | Replays Python's run-detection logic, merges, and galloping breakpoints. |
All algorithms emit immutable Step objects so the UI, export system, and property tests remain in lock-step. Replaying the recorded steps produces the exact sorted output you would get from sorted(data).
- Step model (
src/app/core/step.py): Defines the allowed operations (compare,swap,set,pivot,merge_mark, etc.) and enforces immutability for deterministic replay. - Algorithm registry (
src/app/algos/registry.py): Decorators register algorithms with metadata (stable,in_place, complexity notes, description).load_all_algorithms()eagerly imports every module so the UI and tests can enumerate them. - Visualizer base (
src/app/core/base.py): Contains the shared control bar, canvas rendering, checkpointed replay buffer, export/benchmark logic, preset management, narration, and log viewer hooks. Recent updates improve UI integration and input handling. - Player module (
src/app/core/player.py): Enhanced with proper state management and synchronization features for compare mode. - Presets (
src/app/presets/__init__.py): Central place for dataset generators. Each preset records its key, label, description, and generator callable. - UI layers:
ui_single/holds the production tabbed window (SuiteWindow) and hook-up for the debug dock and theme switching.ui_compare/houses the compare workspace with fixed synchronization and stepping logic.ui_shared/packages reusable widgets (pane HUD, theme helpers, constants, narration cards) with enhanced functionality.
- Core replay helpers (
src/app/core/player.py,replay.py,compare.py): Encapsulate forward/back stepping, GIF frame capture, and dual-pane synchronization. - Native experiments:
native/radix_simd.cppis a standalone NEON prototype for fast digit counting. It is not required for normal operation but documents future optimization ideas.
Install development tooling:
pip install -e .[dev]# Linting and formatting
ruff check src tests
black --check src tests
# Type checking
mypy src
# Run test suite
pytest
# Run specific test categories
pytest tests/test_compare_integration.py # Compare mode tests
pytest tests/test_export_serialization.py # Export functionality tests
pytest tests/test_ui_components.py # UI component testsThe new verify_metrics.py script allows offline verification of algorithm behavior:
# Run metrics verification for specific presets and seeds
python scripts/verify_metrics.py --preset reverse_run --seed 34554345 34554346
# Output to CSV for analysis
python scripts/verify_metrics.py --preset random --csv verify_test.csvThis tool helps validate that algorithms produce expected step counts, comparisons, swaps, and maintain deterministic behavior across runs.
tests/contains comprehensive test coverage:- Property-based checks using Hypothesis
- Deterministic replay validation
- Keyboard shortcut coverage
- Export serialization tests (recently updated)
- UI smoke tests
- Compare mode integration tests with full stepping verification
- Logs live under
~/Library/Logs/org.pysort/sorting-visualizer/on macOS or the platformdirs equivalent on other OSes - The app falls back to
./logs/if platformdirs is unavailable - Comprehensive error handling with rotating log files
docs/ROADMAP.mdtracks upcoming milestonesdocs/audit.mdanddocs/phase.mdstore UX and technical audits- Inline code comments provide implementation details
pysort-visualizer/ # Recently renamed from UI_UPDATE_PYSORT
├── main.py # Entry point that boots the PyQt6 application
├── src/
│ └── app/
│ ├── algos/ # Algorithm implementations + registry
│ │ ├── bubble.py # Recently enhanced with better instrumentation
│ │ ├── insertion.py # Updated with improved step tracking
│ │ └── ... # 14 total algorithm implementations
│ ├── core/ # Visualization engine, replay, exports
│ │ ├── base.py # Recently refactored for better UI integration
│ │ ├── player.py # Enhanced with compare mode fixes
│ │ └── ...
│ ├── presets/ # Dataset generators and metadata
│ ├── ui_single/ # Single visualizer window
│ ├── ui_compare/ # Compare mode (recently fixed!)
│ └── ui_shared/ # Reusable widgets with enhanced functionality
├── scripts/
│ ├── setup.sh # macOS/Linux bootstrap (venv + pip install)
│ ├── setup.bat # Windows bootstrap (venv + pip install)
│ ├── run.sh # macOS/Linux automated launcher
│ ├── run.py # Cross-platform automated launcher
│ └── verify_metrics.py # NEW: Metrics verification tool
├── tests/ # Comprehensive test suite (30+ test files)
├── docs/ # Roadmap, audits, supporting notes
├── native/radix_simd.cpp # Optional SIMD prototype
├── requirements.txt # Runtime dependencies
├── pyproject.toml # Build, lint, and type-check configuration
└── README.md # This file
- Fixed synchronization issues between dual panes
- Proper stepping behavior now ensures both algorithms advance correctly
- Enhanced state management for consistent playback
- Auto-apply input with 1.5-second debounce timer
- Prevents animation restart when sorted array is detected
- Better HUD display and input field state management
- Updated
base.pyandplayer.pyfor better UI integration - Enhanced
pane.pyin ui_shared for improved functionality - Removed deprecated
debug_controls.pymodule
- Added
verify_metrics.pyfor offline algorithm metrics verification - Supports CSV output for detailed analysis
- Validates step counts, comparisons, swaps, and inversions
- Packaging & distribution: Installers and CI pipelines are tracked in
docs/ROADMAP.mdand not yet implemented—run from source for now. - Documentation: CONTRIBUTING guidelines and an in-depth user guide are planned. This README, roadmap, and inline code comments are the authoritative references today.
- Performance optimizations: SIMD implementations for certain algorithms are experimental (see
native/radix_simd.cpp). - Additional algorithms: Future additions may include Introsort, Gnome Sort, and other educational algorithms.
- License: Educator Non-Commercial (see
LICENSE.txt). Contact the maintainer for commercial usage. - Maintainer: Justin Guida — [email protected]
- Repository: https://github.com/jguida941/pysort-visualizer (formerly UI_UPDATE_PYSORT)
- Bug Reports: Please include exported step traces (
Export → CSV) and the RNG seed when reporting bugs.
Enjoy exploring the algorithms!