Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
ed5ba89
wip--remove class from init
zm711 May 2, 2025
270d8af
fix __all__
zm711 May 2, 2025
20c3d97
add __all__ to extractors
zm711 May 2, 2025
3970624
different strategy for displaying dicts
zm711 May 2, 2025
21bea25
different strategy again for __all__
zm711 May 2, 2025
3e9119a
fix sorters
zm711 May 2, 2025
95fd9ea
fix ironclust
zm711 May 2, 2025
85c65af
WIP --fix testing
zm711 May 2, 2025
1d6ccb5
finish fixing testing
zm711 May 2, 2025
c7f58d3
additional fixes
zm711 May 3, 2025
d5f2cf0
preprocessing return function too
zm711 May 5, 2025
ab0081f
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] May 5, 2025
92d7a60
list -> classes
zm711 May 15, 2025
433874b
more list-> classes
zm711 May 15, 2025
71c922f
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] May 15, 2025
9555f85
another classes
zm711 May 15, 2025
9b341d6
fix two docs
zm711 May 15, 2025
dc28af4
Merge branch 'main' into remove-class
zm711 May 15, 2025
b8fcac7
add dep warning to classes
zm711 May 16, 2025
84662f8
fix * import for si.full
zm711 May 16, 2025
8819de9
heberto suggestion
zm711 May 16, 2025
3283df5
Heberto suggestion again
zm711 May 16, 2025
8d5bb91
more doc fixes
zm711 May 16, 2025
3790f32
add dep warning to neo classes
zm711 May 18, 2025
fda7de5
Merge branch 'main' into remove-class
zm711 May 18, 2025
6c6a756
oops
zm711 May 18, 2025
e392a54
merge-main
zm711 Jun 2, 2025
900cdfe
heberto feedback
zm711 Jun 2, 2025
a21b257
better comment + typo fix
zm711 Jun 2, 2025
b0c72c0
typo from fixing merge conflict
zm711 Jun 2, 2025
fbde75f
Merge branch 'main' into remove-class
zm711 Jun 3, 2025
14bfb79
Update src/spikeinterface/extractors/extractor_classes.py
zm711 Jun 3, 2025
59ebeb3
final heberto comments
zm711 Jun 3, 2025
23a024d
Merge branch 'main' into remove-class
zm711 Jun 3, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 6 additions & 6 deletions src/spikeinterface/extractors/__init__.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from .extractor_classes import *

from .toy_example import toy_example
from .bids import read_bids
from .toy_example import toy_example as toy_example
Comment thread
zm711 marked this conversation as resolved.
from .bids import read_bids as read_bids


from .neuropixels_utils import get_neuropixels_channel_groups, get_neuropixels_sample_shifts
Expand Down Expand Up @@ -31,14 +31,15 @@ def __getattr__(extractor_name):
all_extractors += list(event_extractor_full_dict.values())
all_extractors += list(snippets_extractor_full_dict.values())
# special cases because they don't have simple wrappers
Comment thread
chrishalcrow marked this conversation as resolved.
# instead a single wrapper maps to multiple classes so we return
# each class to check it
from .neoextractors import (
MEArecRecordingExtractor,
MEArecSortingExtractor,
OpenEphysBinaryEventExtractor,
OpenEphysBinaryRecordingExtractor,
OpenEphysLegacyRecordingExtractor,
SpikeGLXEventExtractor,
SpikeGLXRecordingExtractor,
)

all_extractors += [
Expand All @@ -48,17 +49,16 @@ def __getattr__(extractor_name):
OpenEphysBinaryRecordingExtractor,
OpenEphysLegacyRecordingExtractor,
SpikeGLXEventExtractor,
SpikeGLXRecordingExtractor,
]
for reading_function in all_extractors:
if extractor_name == reading_function.__name__:
dep_msg = (
"Importing classes at __init__ has been deprecated in favor of only importing functions "
"Importing classes at __init__ has been deprecated in favor of only importing function-size wrappers "
"and will be removed in 0.105.0. For developers that prefer working with the class versions of extractors "
"they can be imported from spikeinterface.extractors.extractor_classes"
)
warn(dep_msg)
return reading_function
# this is necessary for objects that we don't support
# normally this is an ImportError but since this is in the _getattr__ pytest needs an AttributeError
# normally this is an ImportError but since this is in the __getattr__ pytest needs an AttributeError
raise AttributeError(f"cannot import name '{extractor_name}' from '{__name__}'")
33 changes: 25 additions & 8 deletions src/spikeinterface/extractors/extractor_classes.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,14 +77,29 @@


###############################################################################################
# first we line up each class with its wrapper that returns a snakecase version of the class
# that Alessio and Zach like to call the function-version.
# for this to work we need the actual wrapper class (ie the function) along with a string version of wrapper name
# so we make a private nested dict that we can load the wrapper string into the __all__ attribute which means only the
# correct "function"/wrapper class are loaded into the extractors __init__
# note that some formats (binary and numpy) still use the class format as they aren't read-only (ie they have no wrapper)
# the following code is necessary for controlling what the end user imports from spikeinterface.
# The strategy has three goals:
#
# * A mapping from the original class to its wrapper (because that's what we want to expose)
# * A mapping from the original class to its wrapper string (because of __all__)
# * A mapping from format to the class wrapper for convenience (exposed to users for ease of use)
#
# To achieve these there goals we do the following:
#
# 1) we line up each class with its wrapper that returns a snakecase version of the class (in some docs called
# the "function" version, although this is just a wrapper of the underlying class)
# 2) we do (1) by creating nested dicts where the key is the original class and the values are a nested dict with
# 3) a "wrapper_class" key which returns the wrapper to be exposed to the end user and
# 4) a "wrapper_string" which is added to the __all__ attribute of the __init__. This is necessary because __all__
# can only accept a list of strings
# 5) Finally we create dictionaries exposed to the user where we return a formatted file format as a key along
# with the value being the wrapper (see the comment below for examples for this dict)
#
# Note that some formats (e.g. binary and numpy) still use the class format as they aren't read-only (i.e. they
# have no wrapper)

Comment thread
h-mayorquin marked this conversation as resolved.
Comment thread
h-mayorquin marked this conversation as resolved.
_recording_extractor_full_dict = {
# core extractors that are returned as classes
BinaryFolderRecording: dict(wrapper_string="BinaryFolderRecording", wrapper_class=BinaryFolderRecording),
BinaryRecordingExtractor: dict(wrapper_string="BinaryRecordingExtractor", wrapper_class=BinaryRecordingExtractor),
ZarrRecordingExtractor: dict(wrapper_string="ZarrRecordingExtractor", wrapper_class=ZarrRecordingExtractor),
Expand Down Expand Up @@ -143,8 +158,10 @@

############################################################################################################
# Organize the possible extractors into a user facing format with keys being extractor names
# (e.g. 'intan' , 'kilosort') and values being the appropriate Extractor class (e.g. IntanRecordingExtractor,
# KiloSortSortingExtractor)
# (e.g. 'intan' , 'kilosort') and values being the appropriate Extractor class returned as its wrapper
# (e.g. IntanRecordingExtractor, KiloSortSortingExtractor)
# An important note is the the formats are returned after performing `.lower()` so a format like
# SpikeGLX will be a key of 'spikeglx'
# for example if we wanted to create a recording from an intan file we could do the following:
# >>> recording = se.recording_extractor_full_dict['intan'](file_path='path/to/data.rhd')

Expand Down
Loading