-
Notifications
You must be signed in to change notification settings - Fork 260
Remove classes from extractor and preprocessing __init__
#3898
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 33 commits
ed5ba89
270d8af
20c3d97
3970624
21bea25
3e9119a
95fd9ea
85c65af
1d6ccb5
c7f58d3
d5f2cf0
ab0081f
92d7a60
433874b
71c922f
9555f85
9b341d6
dc28af4
b8fcac7
84662f8
8819de9
3283df5
8d5bb91
3790f32
fda7de5
6c6a756
e392a54
900cdfe
a21b257
b0c72c0
fbde75f
14bfb79
59ebeb3
23a024d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,9 +1,64 @@ | ||
| from .extractorlist import * | ||
| from .extractor_classes import * | ||
|
|
||
| from .toy_example import toy_example | ||
| from .bids import read_bids | ||
| from .toy_example import toy_example as toy_example | ||
| from .bids import read_bids as read_bids | ||
|
|
||
|
|
||
| from .neuropixels_utils import get_neuropixels_channel_groups, get_neuropixels_sample_shifts | ||
|
|
||
| from .neoextractors import get_neo_num_blocks, get_neo_streams | ||
|
|
||
| from warnings import warn | ||
|
|
||
|
|
||
| # deprecation of class import idea from neuroconv | ||
| # this __getattr__ is only triggered if the normal lookup fails so import | ||
| # any of our functions is fine but if someone tries to import a class this raises | ||
| # the warning and then returns the "function" version which will look the same | ||
| # to the end-user | ||
| # to be removed after version 0.105.0 | ||
| def __getattr__(extractor_name): | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Amazing, you are doing very sophisticated stuff. Maybe too much for me but I really admire.
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It was a pain to get working. But Heberto makes a great point that we don't want to pull the rug out from under our devs who build off of spikeinterface. So we warn them for a couple versions then wee can clean this all up. |
||
| # we need this trick to allow us to use import * for spikeinterface.full | ||
| if extractor_name == "__all__": | ||
| __all__ = [] | ||
| for imp in globals(): | ||
| # need to remove a bunch of builtins etc that shouldn't be part of all | ||
| if imp[0] != "_" and imp != "warn" and imp != "extractor_name": | ||
| __all__.append(imp) | ||
| return __all__ | ||
| all_extractors = list(recording_extractor_full_dict.values()) | ||
| all_extractors += list(sorting_extractor_full_dict.values()) | ||
| 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 | ||
|
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, | ||
| ) | ||
|
|
||
| all_extractors += [ | ||
| MEArecRecordingExtractor, | ||
| MEArecSortingExtractor, | ||
| OpenEphysBinaryEventExtractor, | ||
| OpenEphysBinaryRecordingExtractor, | ||
| OpenEphysLegacyRecordingExtractor, | ||
| SpikeGLXEventExtractor, | ||
| ] | ||
| 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 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 | ||
| raise AttributeError(f"cannot import name '{extractor_name}' from '{__name__}'") | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,202 @@ | ||
| from __future__ import annotations | ||
|
|
||
|
|
||
| # most important extractor are in spikeinterface.core | ||
| from spikeinterface.core import ( | ||
| BinaryFolderRecording, | ||
| BinaryRecordingExtractor, | ||
| NumpyRecording, | ||
| NpzSortingExtractor, | ||
| NumpySorting, | ||
| NpySnippetsExtractor, | ||
| ZarrRecordingExtractor, | ||
| ZarrSortingExtractor, | ||
|
zm711 marked this conversation as resolved.
|
||
| read_binary, | ||
| read_zarr, | ||
| read_npz_sorting, | ||
| read_npy_snippets, | ||
| ) | ||
|
|
||
| # sorting/recording/event from neo | ||
| from .neoextractors import * | ||
|
|
||
| # non-NEO objects implemented in neo folder | ||
| # keep for reference Currently pulling from neoextractor __init__ | ||
| # from .neoextractors import NeuroScopeSortingExtractor, MaxwellEventExtractor | ||
|
|
||
| # NWB sorting/recording/event | ||
| from .nwbextractors import ( | ||
| NwbRecordingExtractor, | ||
| NwbSortingExtractor, | ||
| NwbTimeSeriesExtractor, | ||
| read_nwb, | ||
| read_nwb_recording, | ||
| read_nwb_sorting, | ||
| read_nwb_timeseries, | ||
| ) | ||
|
|
||
| from .cbin_ibl import CompressedBinaryIblExtractor, read_cbin_ibl | ||
| from .iblextractors import IblRecordingExtractor, IblSortingExtractor, read_ibl_recording, read_ibl_sorting | ||
| from .mcsh5extractors import MCSH5RecordingExtractor, read_mcsh5 | ||
| from .whitematterrecordingextractor import WhiteMatterRecordingExtractor, read_whitematter | ||
|
|
||
| # sorting extractors in relation with a sorter | ||
| from .cellexplorersortingextractor import CellExplorerSortingExtractor, read_cellexplorer | ||
| from .klustaextractors import KlustaSortingExtractor, read_klusta | ||
| from .hdsortextractors import HDSortSortingExtractor, read_hdsort | ||
| from .mclustextractors import MClustSortingExtractor, read_mclust | ||
| from .waveclustextractors import WaveClusSortingExtractor, read_waveclus | ||
| from .yassextractors import YassSortingExtractor, read_yass | ||
| from .combinatoextractors import CombinatoSortingExtractor, read_combinato | ||
| from .tridesclousextractors import TridesclousSortingExtractor, read_tridesclous | ||
| from .spykingcircusextractors import SpykingCircusSortingExtractor, read_spykingcircus | ||
| from .herdingspikesextractors import HerdingspikesSortingExtractor, read_herdingspikes | ||
| from .mdaextractors import MdaRecordingExtractor, MdaSortingExtractor, read_mda_recording, read_mda_sorting | ||
| from .phykilosortextractors import PhySortingExtractor, KiloSortSortingExtractor, read_phy, read_kilosort | ||
| from .sinapsrecordingextractors import ( | ||
| SinapsResearchPlatformRecordingExtractor, | ||
| SinapsResearchPlatformH5RecordingExtractor, | ||
| read_sinaps_research_platform, | ||
| read_sinaps_research_platform_h5, | ||
| ) | ||
|
|
||
| # sorting in relation with simulator | ||
| from .shybridextractors import ( | ||
| SHYBRIDRecordingExtractor, | ||
| SHYBRIDSortingExtractor, | ||
| read_shybrid_recording, | ||
| read_shybrid_sorting, | ||
| ) | ||
|
|
||
| # snippers | ||
| from .waveclussnippetstextractors import WaveClusSnippetsExtractor, read_waveclus_snippets | ||
|
|
||
|
|
||
| # misc | ||
| from .alfsortingextractor import ALFSortingExtractor, read_alf_sorting | ||
|
|
||
|
|
||
| ############################################################################################### | ||
| # 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) | ||
|
|
||
|
h-mayorquin marked this conversation as resolved.
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), | ||
| # natively implemented in spikeinterface.extractors | ||
| NumpyRecording: dict(wrapper_string="NumpyRecording", wrapper_class=NumpyRecording), | ||
| SHYBRIDRecordingExtractor: dict(wrapper_string="read_shybrid_recording", wrapper_class=read_shybrid_recording), | ||
| MdaRecordingExtractor: dict(wrapper_string="read_mda_recording", wrapper_class=read_mda_recording), | ||
| NwbRecordingExtractor: dict(wrapper_string="read_nwb_recording", wrapper_class=read_nwb_recording), | ||
| NwbTimeSeriesExtractor: dict(wrapper_string="read_nwb_timeseries", wrapper_class=read_nwb_timeseries), | ||
| # others | ||
| CompressedBinaryIblExtractor: dict(wrapper_string="read_cbin_ibl", wrapper_class=read_cbin_ibl), | ||
| IblRecordingExtractor: dict(wrapper_string="read_ibl_recording", wrapper_class=read_ibl_recording), | ||
| MCSH5RecordingExtractor: dict(wrapper_string="read_mcsh5", wrapper_class=read_mcsh5), | ||
| SinapsResearchPlatformRecordingExtractor: dict( | ||
| wrapper_string="read_sinaps_research_platform", wrapper_class=read_sinaps_research_platform | ||
| ), | ||
| SinapsResearchPlatformH5RecordingExtractor: dict( | ||
| wrapper_string="read_sinaps_research_platform_h5", wrapper_class=read_sinaps_research_platform_h5 | ||
| ), | ||
| WhiteMatterRecordingExtractor: dict(wrapper_string="read_whitematter", wrapper_class=read_whitematter), | ||
| } | ||
| _recording_extractor_full_dict.update(neo_recording_extractors_dict) | ||
|
|
||
| _sorting_extractor_full_dict = { | ||
| NpzSortingExtractor: dict(wrapper_string="read_npz_sorting", wrapper_class=read_npz_sorting), | ||
| ZarrSortingExtractor: dict(wrapper_string="ZarrSortingExtractor", wrapper_class=ZarrSortingExtractor), | ||
| NumpySorting: dict(wrapper_string="NumpySorting", wrapper_class=NumpySorting), | ||
| # natively implemented in spikeinterface.extractors | ||
| MdaSortingExtractor: dict(wrapper_string="read_mda_sorting", wrapper_class=read_mda_sorting), | ||
| SHYBRIDSortingExtractor: dict(wrapper_string="read_shybrid_sorting", wrapper_class=read_shybrid_sorting), | ||
| ALFSortingExtractor: dict(wrapper_string="read_alf_sorting", wrapper_class=read_alf_sorting), | ||
| KlustaSortingExtractor: dict(wrapper_string="read_klusta", wrapper_class=read_klusta), | ||
| HDSortSortingExtractor: dict(wrapper_string="read_hdsort", wrapper_class=read_hdsort), | ||
| MClustSortingExtractor: dict(wrapper_string="read_mclust", wrapper_class=read_mclust), | ||
| WaveClusSortingExtractor: dict(wrapper_string="read_waveclus", wrapper_class=read_waveclus), | ||
| YassSortingExtractor: dict(wrapper_string="read_yass", wrapper_class=read_yass), | ||
| CombinatoSortingExtractor: dict(wrapper_string="read_combinato", wrapper_class=read_combinato), | ||
| TridesclousSortingExtractor: dict(wrapper_string="read_tridesclous", wrapper_class=read_tridesclous), | ||
| SpykingCircusSortingExtractor: dict(wrapper_string="read_spykingcircus", wrapper_class=read_spykingcircus), | ||
| HerdingspikesSortingExtractor: dict(wrapper_string="read_herdingspikes", wrapper_class=read_herdingspikes), | ||
| KiloSortSortingExtractor: dict(wrapper_string="read_kilosort", wrapper_class=read_kilosort), | ||
| PhySortingExtractor: dict(wrapper_string="read_phy", wrapper_class=read_phy), | ||
| NwbSortingExtractor: dict(wrapper_string="read_nwb_sorting", wrapper_class=read_nwb_sorting), | ||
| IblSortingExtractor: dict(wrapper_string="read_ibl_sorting", wrapper_class=read_ibl_sorting), | ||
| CellExplorerSortingExtractor: dict(wrapper_string="read_cellexplorer", wrapper_class=read_cellexplorer), | ||
| } | ||
| _sorting_extractor_full_dict.update(neo_sorting_extractors_dict) | ||
|
|
||
| # events only from neo | ||
| _event_extractor_full_dict = neo_event_extractors_dict | ||
|
|
||
| _snippets_extractor_full_dict = { | ||
| NpySnippetsExtractor: dict(wrapper_string="read_npy_snippets", wrapper_class=read_npy_snippets), | ||
| WaveClusSnippetsExtractor: dict(wrapper_string="read_waveclus_snippets", wrapper_class=read_waveclus_snippets), | ||
| } | ||
|
|
||
| ############################################################################################################ | ||
| # 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 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') | ||
|
|
||
|
|
||
|
h-mayorquin marked this conversation as resolved.
|
||
| recording_extractor_full_dict = { | ||
| rec_class.__name__.replace("Recording", "").replace("Extractor", "").lower(): rec_func["wrapper_class"] | ||
| for rec_class, rec_func in _recording_extractor_full_dict.items() | ||
| } | ||
| sorting_extractor_full_dict = { | ||
| sort_class.__name__.replace("Sorting", "").replace("Extractor", "").lower(): sort_func["wrapper_class"] | ||
| for sort_class, sort_func in _sorting_extractor_full_dict.items() | ||
| } | ||
| event_extractor_full_dict = { | ||
| event_class.__name__.replace("Event", "").replace("Extractor", "").lower(): event_func["wrapper_class"] | ||
| for event_class, event_func in _event_extractor_full_dict.items() | ||
| } | ||
| snippets_extractor_full_dict = { | ||
| snippets_class.__name__.replace("Snippets", "").replace("Extractor", "").lower(): snippets_func["wrapper_class"] | ||
| for snippets_class, snippets_func in _snippets_extractor_full_dict.items() | ||
| } | ||
|
|
||
|
|
||
| # we only do the functions in the init rather than pull in the classes | ||
|
h-mayorquin marked this conversation as resolved.
|
||
| __all__ = [func["wrapper_string"] for func in _recording_extractor_full_dict.values()] | ||
| __all__ += [func["wrapper_string"] for func in _sorting_extractor_full_dict.values()] | ||
| __all__ += [func["wrapper_string"] for func in _event_extractor_full_dict.values()] | ||
| __all__ += [func["wrapper_string"] for func in _snippets_extractor_full_dict.values()] | ||
| __all__.extend( | ||
| [ | ||
| "read_nwb", # convenience function for multiple nwb formats | ||
| "recording_extractor_full_dict", | ||
| "sorting_extractor_full_dict", | ||
| "event_extractor_full_dict", | ||
| "snippets_extractor_full_dict", | ||
| "read_binary", # convenience function for binary formats | ||
| "read_zarr", | ||
| ] | ||
| ) | ||
Uh oh!
There was an error while loading. Please reload this page.