feat(extension_types): add LogicalSISortingAnalyzer for SpikeInterface SortingAnalyzer objects#207
Conversation
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Add LogicalSISortingAnalyzer logical type for spikeinterface.core.SortingAnalyzer. Stores folder-path JSON (folder + format) instead of to_dict() JSON since SortingAnalyzer is not a BaseExtractor subclass. Includes full python_to_storage and storage_to_python implementations and importable test.
…ts (ITL-469) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Implements SISortingAnalyzerHandler which computes a SHA-256 ContentHash of the folder path string for SortingAnalyzer objects (phase 1 hashing). Adds 3 handler tests covering hash stability, path-based differentiation, and ValueError on in-memory analyzers.
…r (ITL-469) Add isinstance(obj, SortingAnalyzer) type check to SISortingAnalyzerHandler.handle, consistent with SIMotionHandler, SIRecordingHandler, and SISortingHandler, so that passing the wrong type raises a clear TypeError instead of an unguarded AttributeError. Add test_si_sorting_analyzer_handler_type_error to verify the guard. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ikeinterface_types (ITL-469) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
… (ITL-469) Wire LogicalSISortingAnalyzer and SISortingAnalyzerHandler into the public API (__init__.py conditional imports + __all__) and into the default context (v0.1.json logical_types + handlers + changelog). Update module and test docstrings to include ITL-469. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
There was a problem hiding this comment.
Pull request overview
Adds first-class support for SpikeInterface SortingAnalyzer objects in orcapod’s extension-type system by representing them as a folder-backed reference (JSON stored in an Arrow large_string) and providing a semantic-hash handler keyed off the analyzer folder path.
Changes:
- Introduces
LogicalSISortingAnalyzer(JSON{folder, format}storage inpa.large_string()) andSISortingAnalyzerHandler(SHA-256 of folder path string). - Wires the new logical type + handler into SpikeInterface registration, optional exports, and the default context config (
v0.1.json). - Adds comprehensive pytest coverage for serialization, error cases, hashing stability, and registration.
Reviewed changes
Copilot reviewed 6 out of 6 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| tests/test_extension_types/test_spikeinterface_types.py | Adds helper + tests for SortingAnalyzer logical type, hashing handler, and registration wiring. |
| superpowers/specs/2026-07-03-sorting-analyzer-logical-type-design.md | Adds a design/spec document for the new logical type and handler. |
| superpowers/plans/2026-07-03-sorting-analyzer-logical-type.md | Adds an implementation plan detailing stepwise changes and test strategy. |
| src/orcapod/extension_types/spikeinterface_types.py | Implements LogicalSISortingAnalyzer, SISortingAnalyzerHandler, and registers them in register_spikeinterface_types(). |
| src/orcapod/extension_types/init.py | Exposes the new SpikeInterface logical type/handler behind the optional SpikeInterface import gate. |
| src/orcapod/contexts/data/v0.1.json | Adds optional context entries for the new logical type and handler, plus a changelog entry. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| | Logical type name | `"spikeinterface.sorting_analyzer"` | | ||
| | Python type | `spikeinterface.core.SortingAnalyzer` | | ||
| | Arrow storage type | `pa.large_string()` | | ||
| | Arrow extension name | `"orcapod.spikeinterface.sorting_analyzer"` | | ||
|
|
There was a problem hiding this comment.
Fixed in commit 934df86. The spec now reads "spikeinterface.sorting_analyzer" to match the implementation and all other SI logical types (recording, sorting, motion).
| ### `SISortingAnalyzerHandler.handle(analyzer, hasher)` → `ContentHash` | ||
|
|
||
| 1. Check `analyzer.folder is None` → raise `ValueError`. | ||
| 2. Return `ContentHash(hashlib.sha256(str(analyzer.folder).encode()).hexdigest())`. | ||
|
|
There was a problem hiding this comment.
Fixed in commit 934df86. The spec pseudocode now reads ContentHash(method="sha256", digest=hashlib.sha256(str(analyzer.folder).encode()).digest()), matching the actual ContentHash(method: str, digest: bytes) dataclass contract.
- Arrow extension name was "orcapod.spikeinterface.sorting_analyzer"; correct value (matching implementation and all other SI types) is "spikeinterface.sorting_analyzer" - ContentHash pseudocode used .hexdigest() returning str; correct API is ContentHash(method="sha256", digest=...) with raw bytes from .digest()
Review round addressed (Copilot)Both comments pointed to inaccuracies in the spec document only — the implementation was already correct. Changes made (commit
|
| Issue | Fix |
|---|---|
Arrow extension name listed as "orcapod.spikeinterface.sorting_analyzer" |
Corrected to "spikeinterface.sorting_analyzer" — consistent with the implementation and all other SI logical types |
Hashing pseudocode used .hexdigest() (returns str) |
Updated to ContentHash(method="sha256", digest=hashlib.sha256(...).digest()) — matches the actual ContentHash(method: str, digest: bytes) dataclass |
No production code or test changes were required.
…r (ITL-469) - test_si_sorting_analyzer_storage_to_python_bad_json: exercises the except (JSONDecodeError, TypeError) branch in storage_to_python - test_register_spikeinterface_types_sorting_analyzer_reraises_unexpected_error: exercises the re-raise path when register_logical_type raises an unexpected ValueError (no "already bound to" in message) Brings patch coverage for the ITL-469 additions to 100%.
Coverage addressed (Codecov)Codecov reported 3 uncovered lines from the patch in Commit
Patch coverage for the ITL-469 additions is now 100%. The remaining uncovered lines in the file are pre-existing gaps in the older SI types (Recording, Sorting, Motion) not part of this PR's patch. |
Summary
LogicalSISortingAnalyzer— a newBaseLogicalTypethat serialises a folder-backedSortingAnalyzeras apa.large_string()Arrow column containing{"folder": "...", "format": "..."}JSONSISortingAnalyzerHandler— computes aContentHashvia SHA-256 of the folder path string (phase 1; content hashing deferred to ITL-476)register_spikeinterface_types(),extension_types/__init__.py, andcontexts/data/v0.1.json(with_optional: trueso the context degrades gracefully when spikeinterface is not installed)analyzer.folder is None) raise a clearValueErrorat both serialisation and hashing timeTest Plan
test_logical_si_sorting_analyzer_importable— class is importable and has correct attributestest_in_memory_analyzer_raises—python_to_storageraisesValueErrorfor in-memory analyzerstest_binary_folder_analyzer_round_trip— serialise → deserialise round-trip forbinary_folderformattest_zarr_analyzer_round_trip— serialise → deserialise round-trip forzarrformattest_si_sorting_analyzer_handler_hash_stability— same folder → same hash across callstest_si_sorting_analyzer_handler_hash_changes_with_path— different folder → different hashtest_si_sorting_analyzer_handler_in_memory_raises— handler raisesValueErrorfor in-memory analyzertest_si_sorting_analyzer_handler_type_error— handler raisesTypeErrorfor wrong typetest_register_spikeinterface_types_includes_sorting_analyzer— registration wires up the typeCloses ITL-469
🤖 Generated with Claude Code