From e8ae471e775ebae34c15e4ee20708f6aeac2381b Mon Sep 17 00:00:00 2001 From: Eric Denovellis Date: Fri, 2 Feb 2024 16:45:41 -0800 Subject: [PATCH] Filtering units for decoding (#807) * Remove old decoding notebook * Save initial conditions and discrete transitions * Apply suggestions from code review Co-authored-by: Chris Brozdowski * Be more specific with import error * Remove unneeded comments * Remove incorrect dimension name * Project merge_id from SpikeSortingOutput for clarity * Update src/spyglass/decoding/v0/clusterless.py Co-authored-by: Chris Brozdowski * Update src/spyglass/decoding/v0/clusterless.py Co-authored-by: Chris Brozdowski * Update src/spyglass/decoding/v0/clusterless.py Co-authored-by: Chris Brozdowski * Fix linting * Update notebooks * Ignore .pem * Add session as a primary key for Groups * Add some helper methods * Update notebooks * Update README.md * Update pyscripts * Update 42_Decoding_Clusterless.ipynb * Update CHANGELOG.md * Add fetch and insert * Simplify class conversion * Do the dictionary conversion of class for the user * Update CHANGELOG.md * Update .gitignore * Use methods in populate * Avoid fetching interval range if not needed * Generalize finding class from modules * Use args/kwargs * Simplify tuple unpacking * Make decoding kwargs nullable * Add function for get_recording and get_sorting to the spikesorting merge table * make decoding waveform features agnostic to spikesorting source * Fix spelling * Use fetch1_dataframe for position * Use self instead of class * Update src/spyglass/decoding/v1/sorted_spikes.py Co-authored-by: Samuel Bray * Be more careful about populating select keys * Make more readable/remove unused imports * Save classifier * Clean up saved model paths * add function load_linear_position_info * Update src/spyglass/decoding/v1/sorted_spikes.py Co-authored-by: Samuel Bray * Update 41_Extracting_Clusterless_Waveform_Features.py * Update docstring * Apply suggestions from code review Co-authored-by: Chris Brozdowski * Update src/spyglass/decoding/v1/clusterless.py Co-authored-by: Chris Brozdowski * Update src/spyglass/decoding/v1/clusterless.py Co-authored-by: Chris Brozdowski * Fix linting * Fix syntax * Rename variable to avoid confusion * Restrict UnitWaveformFeaturesGroup and SortedSpikesGroup * Concatenate linear position and position dataframes * Static methods don't require instantiating class * Avoid merge restrict * Add version to defaults * Remove unused import * Fix classifier path * Add dry run * Remove non-default * Handle permissions and file not found * Keep position info within encoding/decoding interval * Add methods to get the spike_times, spike_indicators, firing rate * Fix docstring to match default * Implement function rather than import * Remove unused broken imports * Add decoding cleanup * Fix import * Put old vis code back * Fix import * Add draft helper functions * Limit options on input * Fix logic * Fix where the key is passed * Update notebooks * Host main visualizations in non_local_detector repo * Update notebooks/py_scripts/41_Extracting_Clusterless_Waveform_Features.py Co-authored-by: Chris Brozdowski * Update src/spyglass/spikesorting/merge.py Co-authored-by: Chris Brozdowski * Update src/spyglass/decoding/decoding_merge.py Co-authored-by: Chris Brozdowski * Revert "Limit options on input" This reverts commit 386714ccdf480b7d04036b83fb62de6e9164364e. * Use f-string for version * Add useful imports to the top level This would have to change a bit if there were multiple versions of the pipeline. * Make source class a hidden attribute * Update CHANGELOG.md * Centralize get_class logic in Merge (#749) * get_class logic -> dj_merge * blackify --------- Co-authored-by: Eric Denovellis * Add _nwb_table for fetch_nwb * Method is static method * Add merge insert * string split is brittle, use defaults if it didn't work * WIP: Mixin resolves _nwb_table attr for Merge (#783) * Change import * Handle single position 3D case * Fix getting source from key * Use merge_restrict_class for fetch_nwb on merge tables * Move this back * Remove for now * Temp patch for tests * Revert "Temp patch for tests" This reverts commit 281bf3687df74bc7745d435915a57fb8a0597291. * Temp patch for tests * Handle None decoding kwargs * fetch_nwb is a method not a class method now * Fix _merge_repr for numeric data types (#786) * Easily calculate firing rate * Add sorting spike times by place field and ahead behind distance * Account for differently named position variables * Handle orientation name and fix linear position fetch * Fix 2D ahead/behind * Add `UnitSelection` table (#788) * Add UnitSelection * Rename table * Addressing #789, failing tests (#795) * Addressing #789. See details. - Edit settings.py to permit fail to load config on startup - Simplify instructions to use func to generate config, negating need for config.py script - Edit notebook 00 and installation doc to point to save-config func - Expand example config to demonstrate all possible values - Lint dj_merge_table.py to remove unused import and `var is True` * #794 * Fix failing tests * Update Changelog * Typo: chared -> shared * Apply suggestions from code review Co-authored-by: Chris Brozdowski * Fix formatting * Update src/spyglass/common/common_behav.py Co-authored-by: Chris Brozdowski * Update src/spyglass/settings.py Co-authored-by: Chris Brozdowski * Fix syntax * Update merge.py * Revert "Update merge.py" This reverts commit 4e5e5dce6f7829d4453cd6c469b5835c5ef9a89c. * Change load_results to fetch_results for consistency * More load -> fetch * load -> fetch * Use merge table methods * load -> fetch * Rename SortedSpikesGroup.SortGroup to SortedSpikesGroup.Units * Move old spike sorting pipeline to v0 for organizational purposes * Specify full import path * Rename merge module for consistency with other pipelines * Fix import * Fix notebook v0/v1 imports * Fix import * Fix import * Fix import * Fix names * Formatting imports * Remove visualization folder * Move figurl views * Fix formatting for black==24.*.* * Use full import path * Fix method name * Add UnitInclusion merge table * Update 43_Decoding_SortedSpikes.py * Update pyscripts * Remove unneeded sections * Move import inside function * Fix versioning * Fix versioning * Be more uniform about explicit imports * Update CHANGELOG.md * Fix import * Fix #752 * Make imports more explicit * Only import cv2 when needed because it sometimes causes issues * Remove position tools as dependency The functions are relatively simple so copying them over doesn't cause much burden * Fix import name * Rename to linearization_merge for consistency with other modules * Reduce cv2 dependency * Remove unused import * Remove defaults channel to avoid issues * Remove position tools dependency * Add opencv dependency position tools had this as a dependency but since this is removed * Revert "Remove position tools as dependency" This reverts commit 35cd5eddbbb43cad93c6ba4b2cadd2dca953ae74. * Revert "Remove position tools dependency" This reverts commit 451e05836655e7806580d1191c9f3f61cc25e1ca. * Revert "Add opencv dependency" This reverts commit 996be9b0928e5cc30b17137cc08d5fda9b0927fc. * Update dependencies to match environment.yml * Update environment_position.yml * Add figure 1 image and pypi version badge * Update citation * Update to add all authors * Add features to readme * Create CODE_OF_CONDUCT.md * Create .mailmap * Update .mailmap * Fix linting * Remove unused tables * Fix imports * Don't make time relative * Move sorted spikes group to spikesorting * Add MUA detection * Update CHANGELOG.md * Handle discrete states and squeeze to avoid intervals if possible * Fix table name * Add intervallist to exclude artifacts * Remove .mailmap * Revert "Add intervallist to exclude artifacts" This reverts commit 205874a0cab45052dc2c2696f3ef0e8c60d01eb3. * Apply suggestions from code review Co-authored-by: Chris Brozdowski * Revert "Revert "Add intervallist to exclude artifacts"" This reverts commit e102646f8ed69a50125b3ee882fd759e9269c2d4. * remove interval list * Fix linting * Fix linting * Add missing authors * Update CHANGELOG.md * Fix schema name * Remove unused imports * Revert back * Use quotes * Fix name * Move mua because of dependency on position * Fix prefix * Fix schema prefix * Fix name * Add mua * Update 51_MUA_Detection.ipynb * Update src/spyglass/spikesorting/v1/unit_inclusion.py Co-authored-by: Chris Brozdowski * Imported spikes annotation * Fix name of annotated keys and add documentation * Enable SortedSpikesGroup to filter directly on the SpikeSortingOutput nwb file * improve filter_units execution * Apply suggestions from code review Co-authored-by: Chris Brozdowski * style cleanup * remove UnitInclusion tables * fix fetch_spike_data for case where no units in merge id * Update src/spyglass/decoding/v1/sorted_spikes.py Co-authored-by: Samuel Bray * rename UnitSelectionParams * updated sorted decoding notebook * fix linting * fix linting * Fix spelling * Fix import order * Squeeze posterior * Make spike indicator 2D * insert class contents --------- Co-authored-by: Chris Brozdowski Co-authored-by: Sam Bray Co-authored-by: Kyu Hyun Lee --- CHANGELOG.md | 16 +- CITATION.cff | 159 +- CODE_OF_CONDUCT.md | 133 + README.md | 57 +- dj_local_conf_example.json | 2 +- docs/src/contribute.md | 2 +- environment_position.yml | 10 +- notebooks/10_Spike_SortingV0.ipynb | 137 +- notebooks/10_Spike_SortingV1.ipynb | 4 +- ...{11_Curation.ipynb => 11_CurationV0.ipynb} | 2 +- notebooks/21_DLC.ipynb | 3 - notebooks/22_DLC_Loop.ipynb | 3 - ...acting_Clusterless_Waveform_Features.ipynb | 4 +- notebooks/42_Decoding_Clusterless.ipynb | 279 +- notebooks/43_Decoding_SortedSpikes.ipynb | 768 ++--- notebooks/51_MUA_Detection.ipynb | 2808 +++++++++++++++++ notebooks/py_scripts/10_Spike_SortingV0.py | 21 +- notebooks/py_scripts/10_Spike_SortingV1.py | 2 +- .../{11_Curation.py => 11_CurationV0.py} | 2 +- notebooks/py_scripts/24_Linearization.py | 2 +- notebooks/py_scripts/32_Ripple_Detection.py | 2 +- ...xtracting_Clusterless_Waveform_Features.py | 6 +- .../py_scripts/42_Decoding_Clusterless.py | 45 +- .../py_scripts/43_Decoding_SortedSpikes.py | 71 +- notebooks/py_scripts/51_MUA_Detection.py | 241 ++ pyproject.toml | 52 +- src/spyglass/__init__.py | 2 +- src/spyglass/cli/__init__.py | 2 +- src/spyglass/common/__init__.py | 54 +- src/spyglass/common/common_position.py | 3 +- src/spyglass/common/populate_all_common.py | 3 +- src/spyglass/data_import/__init__.py | 2 +- src/spyglass/decoding/decoding_merge.py | 100 +- src/spyglass/decoding/v0/clusterless.py | 87 +- src/spyglass/decoding/v0/sorted_spikes.py | 2 +- .../decoding/v0/visualization_2D_view.py | 4 - src/spyglass/decoding/v1/clusterless.py | 32 +- src/spyglass/decoding/v1/sorted_spikes.py | 166 +- src/spyglass/decoding/v1/waveform_features.py | 4 +- src/spyglass/lfp/__init__.py | 2 +- src/spyglass/lfp/analysis/v1/__init__.py | 2 +- src/spyglass/lfp/v1/__init__.py | 6 +- src/spyglass/lfp/v1/lfp.py | 2 - src/spyglass/linearization/v1/main.py | 2 +- src/spyglass/lock/file_lock.py | 2 +- .../visualization => mua}/__init__.py | 0 src/spyglass/mua/v1/__init__.py | 0 src/spyglass/mua/v1/mua.py | 112 + src/spyglass/position/__init__.py | 2 +- .../position/v1/position_dlc_centroid.py | 12 +- .../position/v1/position_dlc_cohort.py | 10 +- .../position/v1/position_dlc_orient.py | 9 +- .../v1/position_dlc_pose_estimation.py | 5 +- .../position/v1/position_dlc_position.py | 7 +- .../position/v1/position_dlc_project.py | 9 +- .../position/v1/position_dlc_selection.py | 18 +- .../position/v1/position_dlc_training.py | 5 +- .../position/v1/position_trodes_position.py | 12 +- src/spyglass/ripple/v1/__init__.py | 2 +- src/spyglass/ripple/v1/ripple.py | 1 - src/spyglass/sharing/__init__.py | 2 +- src/spyglass/sharing/sharing_kachery.py | 5 +- src/spyglass/spikesorting/__init__.py | 40 - .../spikesorting/analysis/__init__.py | 0 .../spikesorting/analysis/v1/__init__.py | 0 .../spikesorting/analysis/v1/group.py | 205 ++ .../spikesorting/figurl_views/__init__.py | 2 - src/spyglass/spikesorting/imported.py | 96 +- .../{merge.py => spikesorting_merge.py} | 4 +- src/spyglass/spikesorting/v0/__init__.py | 45 + .../spikesorting/{ => v0}/curation_figurl.py | 8 +- .../figurl_views/SpikeSortingRecordingView.py | 4 +- .../{ => v0}/figurl_views/SpikeSortingView.py | 7 +- .../spikesorting/v0/figurl_views/__init__.py | 6 + .../prepare_spikesortingview_data.py | 0 .../{ => v0}/merged_sorting_extractor.py | 0 .../spikesorting/{ => v0}/sortingview.py | 10 +- .../{ => v0}/sortingview_helper_fn.py | 2 +- .../{ => v0}/spikesorting_artifact.py | 4 +- .../{ => v0}/spikesorting_curation.py | 9 +- .../{ => v0}/spikesorting_populator.py | 10 +- .../{ => v0}/spikesorting_recording.py | 0 .../{ => v0}/spikesorting_sorting.py | 4 +- src/spyglass/spikesorting/v1/__init__.py | 21 +- src/spyglass/spikesorting/v1/metric_utils.py | 2 +- src/spyglass/spikesorting/v1/utils.py | 2 +- src/spyglass/utils/database_settings.py | 1 + tests/conftest.py | 4 +- 88 files changed, 4906 insertions(+), 1099 deletions(-) create mode 100644 CODE_OF_CONDUCT.md rename notebooks/{11_Curation.ipynb => 11_CurationV0.ipynb} (99%) create mode 100644 notebooks/51_MUA_Detection.ipynb rename notebooks/py_scripts/{11_Curation.py => 11_CurationV0.py} (98%) create mode 100644 notebooks/py_scripts/51_MUA_Detection.py rename src/spyglass/{decoding/visualization => mua}/__init__.py (100%) create mode 100644 src/spyglass/mua/v1/__init__.py create mode 100644 src/spyglass/mua/v1/mua.py create mode 100644 src/spyglass/spikesorting/analysis/__init__.py create mode 100644 src/spyglass/spikesorting/analysis/v1/__init__.py create mode 100644 src/spyglass/spikesorting/analysis/v1/group.py delete mode 100644 src/spyglass/spikesorting/figurl_views/__init__.py rename src/spyglass/spikesorting/{merge.py => spikesorting_merge.py} (96%) create mode 100644 src/spyglass/spikesorting/v0/__init__.py rename src/spyglass/spikesorting/{ => v0}/curation_figurl.py (96%) rename src/spyglass/spikesorting/{ => v0}/figurl_views/SpikeSortingRecordingView.py (97%) rename src/spyglass/spikesorting/{ => v0}/figurl_views/SpikeSortingView.py (94%) create mode 100644 src/spyglass/spikesorting/v0/figurl_views/__init__.py rename src/spyglass/spikesorting/{ => v0}/figurl_views/prepare_spikesortingview_data.py (100%) rename src/spyglass/spikesorting/{ => v0}/merged_sorting_extractor.py (100%) rename src/spyglass/spikesorting/{ => v0}/sortingview.py (96%) rename src/spyglass/spikesorting/{ => v0}/sortingview_helper_fn.py (98%) rename src/spyglass/spikesorting/{ => v0}/spikesorting_artifact.py (99%) rename src/spyglass/spikesorting/{ => v0}/spikesorting_curation.py (99%) rename src/spyglass/spikesorting/{ => v0}/spikesorting_populator.py (97%) rename src/spyglass/spikesorting/{ => v0}/spikesorting_recording.py (100%) rename src/spyglass/spikesorting/{ => v0}/spikesorting_sorting.py (98%) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9b638945d..f4d9e3259 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,6 +18,15 @@ - Increase pytest coverage for `common`, `lfp`, and `utils`. #743 - Update docs to reflect new notebooks. #776 - Add overview of Spyglass to docs. #779 +- Update linting for Black 24. #808 + +### Pipelines + +- Spike sorting: + - Add SpikeSorting V1 pipeline. #651 + - Move modules into spikesorting.v0 #807 + - Add MUA analysis to spike sorting pipeline +- LFP: Minor fixes to LFPBandV1 populator and `make`. #706, #795 ### Pipelines @@ -32,13 +41,18 @@ - Position: - Refactor input validation in DLC pipeline. #688 - DLC path handling from config, and normalize naming convention. #722 + - Fix in place column bug #752 - Decoding: - Add `decoding` pipeline V1. #731, #769 - Add a table to store the decoding results #731 - Use the new `non_local_detector` package for decoding #731 - - Allow multiple spike waveform features for clusterelss decoding #731 + - Allow multiple spike waveform features for clusterless decoding #731 - Reorder notebooks #731 - Add fetch class functionality to `Merge` table. #783, #786 + - Add ability to filter sorted units in decoding #807 + - Rename SortedSpikesGroup.SortGroup to SortedSpikesGroup.Units #807 + - Change methods with load_... to fetch_... for consistency #807 + - Use merge table methods to access part methods #807 ## [0.4.3] (November 7, 2023) diff --git a/CITATION.cff b/CITATION.cff index fa138ea8d..4dce7514b 100644 --- a/CITATION.cff +++ b/CITATION.cff @@ -1,15 +1,150 @@ +# This CITATION.cff file was generated with cffinit. +# Visit https://bit.ly/cffinit to generate yours today! + cff-version: 1.2.0 -message: "If you use this software, please cite it as below." +title: spyglass +message: 'If you use this software, please cite it as below.' +type: software authors: -- family-names: "Lee" - given-names: "Kyu Hyun" -- family-names: "Denovellis" - given-names: "Eric" -- family-names: "Ly" - given-names: "Ryan" -- family-names: "Frank" - given-names: "Loren" -title: "spyglass" + - given-names: Kyu Hyun + family-names: Lee + email: kyuhyun.lee@ucsf.edu + affiliation: 'University of California, San Francisco' + orcid: 'https://orcid.org/0000-0001-6483-9444' + - given-names: Eric L. + family-names: Denovellis + email: eric.denovellis@ucsf.edu + affiliation: Howard Hughes Medical Institute + orcid: 'https://orcid.org/0000-0003-4606-087X' + - given-names: Ryan + family-names: Ly + email: rly@lbl.gov + affiliation: Lawrence Berkeley National Laboratory + orcid: 'https://orcid.org/0000-0001-9238-0642' + - given-names: Jeremy + family-names: Magland + email: jmagland@flatironinstitute.org + affiliation: Flatiron Institute + orcid: 'https://orcid.org/0000-0002-5286-4375' + - given-names: Jeff + family-names: Soules + email: jsoules@flatironinstitute.org + affiliation: Flatiron Institute + - given-names: Alison E. + family-names: Comrie + orcid: 'https://orcid.org/0000-0002-2251-4892' + email: alison.comrie@ucsf.edu + affiliation: 'University of California, San Francisco' + - given-names: Daniel P. + family-names: Gramling + orcid: 'https://orcid.org/0009-0004-6136-3769' + affiliation: University of Tübingen + - given-names: Jennifer A. + family-names: Guidera + email: jennifer.guidera@ucsf.edu + affiliation: 'University of California, San Francisco' + orcid: 'https://orcid.org/0000-0003-4013-214X' + - given-names: Rhino + family-names: Nevers + email: rhino.nevers@ucsf.edu + affiliation: 'University of California, San Francisco' + - given-names: Philip + family-names: Adenekan + email: phil.adenekan@ucsf.edu + affiliation: 'University of California, San Francisco' + orcid: 'https://orcid.org/0000-0002-4999-7847' + - given-names: Chris + family-names: Brozdowski + email: chris.broz@ucsf.edu + affiliation: 'University of California, San Francisco' + orcid: 'https://orcid.org/0000-0002-3055-6718' + - given-names: Samuel + family-names: Bray + email: sam.bray@ucsf.edu + orcid: 'https://orcid.org/0000-0002-9696-6920' + affiliation: 'University of California, San Francisco' + - given-names: Emily + family-names: Monroe + affiliation: University of California, Davis + - given-names: Ji Hyun + family-names: Bak + orcid: 'https://orcid.org/0000-0002-5700-7823' + - given-names: Michael E. + family-names: Coulter + email: michael.coulter@ucsf.edu + orcid: 'https://orcid.org/0000-0003-0357-351X' + affiliation: 'University of California, San Francisco' + - given-names: Xulu + family-names: Sun + email: xulu.sun@ucsf.edu + affiliation: 'University of California, San Francisco' + orcid: 'https://orcid.org/0000-0003-3076-0994' + - given-names: Andrew + family-names: Tritt + email: ajtritt@lbl.gov + affiliation: Lawrence Berkeley National Laboratory + orcid: 'https://orcid.org/0000-0002-1617-449X' + - given-names: Oliver + family-names: Rübel + email: oruebel@lbl.gov + affiliation: Lawrence Berkeley National Laboratory + orcid: 'https://orcid.org/0000-0001-9902-1984' + - given-names: Thinh + family-names: Nguyen + affiliation: Datajoint + email: thinh@datajoint.com + - given-names: Dimitri + family-names: Yatsenko + email: dimitri@datajoint.com + affiliation: Datajoint + orcid: 'https://orcid.org/0000-0002-1844-641X' + - given-names: Joshua + family-names: Chu + email: jpc6@rice.edu + affiliation: Rice University + - given-names: Caleb + family-names: Kemere + email: caleb.kemere@rice.edu + affiliation: Rice University + orcid: 'https://orcid.org/0000-0003-2054-0234' + - given-names: Samuel + family-names: Garcia + email: samuel.garcia@cnrs.fr + affiliation: 'Centre de Recherche en Neurosciences de Lyon' + orcid: 'https://orcid.org/0000-0001-6389-9779' + - given-names: Alessio + family-names: Buccino + email: alessio.buccino@alleninstitute.org + affiliation: Allen Institute + orcid: 'https://orcid.org/0000-0003-3661-527X' + - given-names: Loren M. + family-names: Frank + email: loren.frank@ucsf.edu + affiliation: 'University of California, San Francisco' + orcid: 'https://orcid.org/0000-0002-1752-5677' +identifiers: + - type: doi + value: 10.1101/2024.01.25.577295 + description: bioRxiv preprint +repository-code: 'https://github.com/LorenFrankLab/spyglass' +url: 'https://lorenfranklab.github.io/spyglass/' +abstract: >- + Spyglass is a data analysis framework that facilitates the + storage, analysis, visualization, and sharing of + neuroscience data to support reproducible research. It is + designed to be interoperable with the NWB format and + integrates open-source tools into a coherent framework. +keywords: + - neuroscience + - open science + - electrophysiology + - figurl + - interactive data visualization + - Neurodata Without Borders + - Spike interface + - Datajoint + - spike sorting + - kachery +license: MIT version: 0.4.3 -date-released: 2023-11-07 -url: "https://github.com/LorenFrankLab/spyglass" +date-released: '2023-11-07' diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md new file mode 100644 index 000000000..d146e54a8 --- /dev/null +++ b/CODE_OF_CONDUCT.md @@ -0,0 +1,133 @@ + +# Contributor Covenant Code of Conduct + +## Our Pledge + +We as members, contributors, and leaders pledge to make participation in our +community a harassment-free experience for everyone, regardless of age, body +size, visible or invisible disability, ethnicity, sex characteristics, gender +identity and expression, level of experience, education, socio-economic status, +nationality, personal appearance, race, caste, color, religion, or sexual +identity and orientation. + +We pledge to act and interact in ways that contribute to an open, welcoming, +diverse, inclusive, and healthy community. + +## Our Standards + +Examples of behavior that contributes to a positive environment for our +community include: + +* Demonstrating empathy and kindness toward other people +* Being respectful of differing opinions, viewpoints, and experiences +* Giving and gracefully accepting constructive feedback +* Accepting responsibility and apologizing to those affected by our mistakes, + and learning from the experience +* Focusing on what is best not just for us as individuals, but for the overall + community + +Examples of unacceptable behavior include: + +* The use of sexualized language or imagery, and sexual attention or advances of + any kind +* Trolling, insulting or derogatory comments, and personal or political attacks +* Public or private harassment +* Publishing others' private information, such as a physical or email address, + without their explicit permission +* Other conduct which could reasonably be considered inappropriate in a + professional setting + +## Enforcement Responsibilities + +Community leaders are responsible for clarifying and enforcing our standards of +acceptable behavior and will take appropriate and fair corrective action in +response to any behavior that they deem inappropriate, threatening, offensive, +or harmful. + +Community leaders have the right and responsibility to remove, edit, or reject +comments, commits, code, wiki edits, issues, and other contributions that are +not aligned to this Code of Conduct, and will communicate reasons for moderation +decisions when appropriate. + +## Scope + +This Code of Conduct applies within all community spaces, and also applies when +an individual is officially representing the community in public spaces. +Examples of representing our community include using an official e-mail address, +posting via an official social media account, or acting as an appointed +representative at an online or offline event. + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be +reported to the community leaders responsible for enforcement at +eric.denovellis@ucsf.edu. +All complaints will be reviewed and investigated promptly and fairly. + +All community leaders are obligated to respect the privacy and security of the +reporter of any incident. + +## Enforcement Guidelines + +Community leaders will follow these Community Impact Guidelines in determining +the consequences for any action they deem in violation of this Code of Conduct: + +### 1. Correction + +**Community Impact**: Use of inappropriate language or other behavior deemed +unprofessional or unwelcome in the community. + +**Consequence**: A private, written warning from community leaders, providing +clarity around the nature of the violation and an explanation of why the +behavior was inappropriate. A public apology may be requested. + +### 2. Warning + +**Community Impact**: A violation through a single incident or series of +actions. + +**Consequence**: A warning with consequences for continued behavior. No +interaction with the people involved, including unsolicited interaction with +those enforcing the Code of Conduct, for a specified period of time. This +includes avoiding interactions in community spaces as well as external channels +like social media. Violating these terms may lead to a temporary or permanent +ban. + +### 3. Temporary Ban + +**Community Impact**: A serious violation of community standards, including +sustained inappropriate behavior. + +**Consequence**: A temporary ban from any sort of interaction or public +communication with the community for a specified period of time. No public or +private interaction with the people involved, including unsolicited interaction +with those enforcing the Code of Conduct, is allowed during this period. +Violating these terms may lead to a permanent ban. + +### 4. Permanent Ban + +**Community Impact**: Demonstrating a pattern of violation of community +standards, including sustained inappropriate behavior, harassment of an +individual, or aggression toward or disparagement of classes of individuals. + +**Consequence**: A permanent ban from any sort of public interaction within the +community. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant][homepage], +version 2.1, available at +[https://www.contributor-covenant.org/version/2/1/code_of_conduct.html][v2.1]. + +Community Impact Guidelines were inspired by +[Mozilla's code of conduct enforcement ladder][Mozilla CoC]. + +For answers to common questions about this code of conduct, see the FAQ at +[https://www.contributor-covenant.org/faq][FAQ]. Translations are available at +[https://www.contributor-covenant.org/translations][translations]. + +[homepage]: https://www.contributor-covenant.org +[v2.1]: https://www.contributor-covenant.org/version/2/1/code_of_conduct.html +[Mozilla CoC]: https://github.com/mozilla/diversity +[FAQ]: https://www.contributor-covenant.org/faq +[translations]: https://www.contributor-covenant.org/translations diff --git a/README.md b/README.md index 821b7c4a3..c627581ff 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,55 @@ # spyglass [![Import test](https://github.com/LorenFrankLab/spyglass/actions/workflows/workflow.yml/badge.svg)](https://github.com/LorenFrankLab/spyglass/actions/workflows/workflow.yml) +[![PyPI version](https://badge.fury.io/py/spyglass-neuro.svg)](https://badge.fury.io/py/spyglass-neuro) + +![Spyglass Figure](docs/src/images/fig1.png) `spyglass` is a data analysis framework that facilitates the storage, analysis, visualization, and sharing of neuroscience data to support reproducible research. It is designed to be interoperable with the NWB format and integrates open-source tools into a coherent framework. +Features of Spyglass include: + +- **Standardized data storage** - Spyglass uses the open-source + [Neurodata Without Borders: Neurophysiology (NWB:N)](https://www.nwb.org/) + format to ingest and store processed data. NWB:N is a standard set by the + BRAIN Initiative for neurophysiological data + ([Rübel et al., 2022](https://doi.org/10.7554/elife.78362)). +- **Reproducible analysis** - Spyglass uses [DataJoint](https://datajoint.com/) + to ensure that all analysis is reproducible. DataJoint is a data management + system that automatically tracks dependencies between data and analysis + code. This ensures that all analysis is reproducible and that the results + are automatically updated when the data or analysis code changes. +- **Common analysis tools** - Spyglass provides easy usage of the open-source + packages [SpikeInterface](https://github.com/SpikeInterface/spikeinterface), + [Ghostipy](https://github.com/kemerelab/ghostipy), and + [DeepLabCut](https://github.com/DeepLabCut/DeepLabCut) for common analysis + tasks. These packages are well-documented and have active developer + communities. +- **Interactive data visualization** - Spyglass uses + [figurl](https://github.com/flatironinstitute/figurl) to create interactive + data visualizations that can be shared with collaborators and the broader + community. These visualizations are hosted on the web and can be viewed in + any modern web browser. The interactivity allows users to explore the data + and analysis results in detail. +- **Sharing results** - Spyglass enables sharing of data and analysis results + via [Kachery](https://github.com/flatironinstitute/kachery-cloud), a + decentralized content addressable data sharing platform. Kachery Cloud + allows users to access the database and pull data and analysis results + directly to their local machine. +- **Pipeline versioning** - Processing and analysis of data in neuroscience is + often dynamic, requiring new features. Spyglass uses *Merge tables* to + ensure that analysis pipelines can be versioned. This allows users to easily + use and compare results from different versions of the analysis pipeline + while retaining the ability to access previously generated results. +- **Cautious Delete** - Spyglass uses a `cautious delete` feature to ensure that + data is not accidentally deleted by other users. When a user deletes data, + Spyglass will first check to see if the data belongs to another team of + users. This enables teams of users to work collaboratively on the same + database without worrying about accidentally deleting each other's data. + Documentation can be found at - [https://lorenfranklab.github.io/spyglass/](https://lorenfranklab.github.io/spyglass/) @@ -36,10 +79,10 @@ License and Copyright notice can be found at ## Citation -Kyu Hyun Lee, Eric Denovellis, Ryan Ly, Jeremy Magland, Jeff Soules, Alison -Comrie, Jennifer Guidera, Rhino Nevers, Daniel Gramling, Philip Adenekan, Ji -Hyun Bak, Emily Monroe, Andrew Tritt, Oliver Rübel, Thinh Nguyen, Dimitri -Yatsenko, Joshua Chu, Caleb Kemere, Samuel Garcia, Alessio Buccino, Emily Aery -Jones, Lisa Giocomo, and Loren Frank. Spyglass: A Data Analysis Framework for -Reproducible and Shareable Neuroscience Research. Neuroscience Meeting Planner. -San Diego, CA: Society for Neuroscience, 2022. +> Lee, K.H.\*, Denovellis, E.L.\*, Ly, R., Magland, J., Soules, J., Gramling, D.P., + Guidera, J.A., Nevers, R., Adenekan, P., Bray, S., et al. (2024). Spyglass: +a data analysis framework for reproducible and shareable neuroscience research. + bioRxiv. + [10.1101/2024.01.25.577295](https://doi.org/10.1101/2024.01.25.577295 ). + +*\* Equal contribution* diff --git a/dj_local_conf_example.json b/dj_local_conf_example.json index 1360fb7a0..defdea4d7 100644 --- a/dj_local_conf_example.json +++ b/dj_local_conf_example.json @@ -53,4 +53,4 @@ }, "kachery_zone": "franklab.default" } -} +} \ No newline at end of file diff --git a/docs/src/contribute.md b/docs/src/contribute.md index 7fb8b8b7f..4d41569c0 100644 --- a/docs/src/contribute.md +++ b/docs/src/contribute.md @@ -102,7 +102,7 @@ session. - one or more NWB or data tables - optionally, one or more parameter tables - Non-primary key: None -- Examples: `MetricSelection`, `LFPSElection` +- Examples: `MetricSelection`, `LFPSelection` It is possible for a Selection table to collect information from more than one Parameter table. For example, the Selection table for spike sorting holds diff --git a/environment_position.yml b/environment_position.yml index 8e2d05275..125754062 100644 --- a/environment_position.yml +++ b/environment_position.yml @@ -13,24 +13,20 @@ name: spyglass-position channels: - conda-forge - - defaults - pytorch - franklab - edeno dependencies: - python>=3.9, <3.10 - jupyterlab>=3.* - - pydotplus>=2.0.* + - pydotplus - libgcc - dask>=2.30 - - dask-cuda - - cupy - - pip>=20.2.* + - pip - position_tools - track_linearization>=2.3 - - replay_trajectory_classification - ripple_detection - - trajectory_analysis_tools + - non_local_detector - ipython - matplotlib>=3.3 - seaborn diff --git a/notebooks/10_Spike_SortingV0.ipynb b/notebooks/10_Spike_SortingV0.ipynb index 71abbd3eb..4c9e50ff6 100644 --- a/notebooks/10_Spike_SortingV0.ipynb +++ b/notebooks/10_Spike_SortingV0.ipynb @@ -84,7 +84,7 @@ "dj.config.load(\"dj_local_conf.json\") # load config for database connection info\n", "\n", "import spyglass.common as sgc\n", - "import spyglass.spikesorting as sgs\n", + "import spyglass.spikesorting.v0 as sgs\n", "\n", "# ignore datajoint+jupyter async warnings\n", "import warnings\n", @@ -109,19 +109,120 @@ }, { "cell_type": "code", - "execution_count": 14, + "execution_count": 2, "metadata": {}, - "outputs": [], + "outputs": [ + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " Information about lab member in the context of Frank lab network\n", + "
\n", + " \n", + " \n", + " \n", + "\n", + "\n", + "\n", + "
\n", + "

lab_member_name

\n", + " \n", + "
\n", + "

google_user_name

\n", + " For permission to curate\n", + "
\n", + "

datajoint_user_name

\n", + " For permission to delete\n", + "
\n", + "

admin

\n", + " Ignore permission checks\n", + "
Firstname Lastnameexample@gmail.comuser0
\n", + " \n", + "

Total: 1

\n", + " " + ], + "text/plain": [ + "*lab_member_na google_user_na datajoint_user admin \n", + "+------------+ +------------+ +------------+ +-------+\n", + "Firstname Last example@gmail. user 0 \n", + " (Total: 1)" + ] + }, + "execution_count": 2, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ - "name, email, dj_user = \"Firstname Lastname\", \"example@gmail.com\", \"user\"\n", + "# Full name, Google email address, DataJoint username, admin\n", + "name, email, dj_user, admin = (\n", + " \"Firstname Lastname\",\n", + " \"example@gmail.com\",\n", + " \"user\",\n", + " 0,\n", + ")\n", "sgc.LabMember.insert_from_name(name)\n", "sgc.LabMember.LabMemberInfo.insert1(\n", - " [name, email, dj_user], skip_duplicates=True\n", - ")\n", - "sgc.LabTeam.LabTeamMember.insert1(\n", - " {\"team_name\": \"My Team\", \"lab_member_name\": name},\n", + " [\n", + " name,\n", + " email,\n", + " dj_user,\n", + " admin,\n", + " ],\n", " skip_duplicates=True,\n", - ")" + ")\n", + "sgc.LabMember.LabMemberInfo()" ] }, { @@ -137,17 +238,9 @@ }, { "cell_type": "code", - "execution_count": 15, + "execution_count": 3, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "You made it in!\n" - ] - } - ], + "outputs": [], "source": [ "my_team_members = (\n", " (sgc.LabTeam.LabTeamMember & {\"team_name\": \"My Team\"})\n", @@ -206,8 +299,6 @@ "name": "stderr", "output_type": "stream", "text": [ - "/home/cb/wrk/spyglass/src/spyglass/data_import/insert_sessions.py:41: UserWarning: Cannot insert data from minirec20230622.nwb: minirec20230622_.nwbis already in Nwbfile table.\n", - " warnings.warn(\n" ] } ], @@ -1013,7 +1104,7 @@ }, { "cell_type": "code", - "execution_count": 38, + "execution_count": null, "metadata": {}, "outputs": [ { @@ -2429,7 +2520,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.9.16" + "version": "3.9.18" }, "vscode": { "interpreter": { diff --git a/notebooks/10_Spike_SortingV1.ipynb b/notebooks/10_Spike_SortingV1.ipynb index 1372bdb3c..0c00fc498 100644 --- a/notebooks/10_Spike_SortingV1.ipynb +++ b/notebooks/10_Spike_SortingV1.ipynb @@ -739,7 +739,7 @@ "metadata": {}, "outputs": [], "source": [ - "from spyglass.spikesorting.merge import SpikeSortingOutput" + "from spyglass.spikesorting.spikesorting_merge import SpikeSortingOutput" ] }, { @@ -827,7 +827,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.8.13" + "version": "3.9.18" } }, "nbformat": 4, diff --git a/notebooks/11_Curation.ipynb b/notebooks/11_CurationV0.ipynb similarity index 99% rename from notebooks/11_Curation.ipynb rename to notebooks/11_CurationV0.ipynb index 36ecfd6c4..78cb5caa6 100644 --- a/notebooks/11_Curation.ipynb +++ b/notebooks/11_CurationV0.ipynb @@ -70,7 +70,7 @@ " os.chdir(\"..\")\n", "dj.config.load(\"dj_local_conf.json\") # load config for database connection info\n", "\n", - "from spyglass.spikesorting import SpikeSorting" + "from spyglass.spikesorting.v0 import SpikeSorting" ] }, { diff --git a/notebooks/21_DLC.ipynb b/notebooks/21_DLC.ipynb index aa8f0863b..9bd492720 100644 --- a/notebooks/21_DLC.ipynb +++ b/notebooks/21_DLC.ipynb @@ -109,13 +109,10 @@ "source": [ "import os\n", "import datajoint as dj\n", - "from pprint import pprint\n", "\n", "import spyglass.common as sgc\n", "import spyglass.position.v1 as sgp\n", "\n", - "from pathlib import Path, PosixPath, PurePath\n", - "import glob\n", "import numpy as np\n", "import pandas as pd\n", "import pynwb\n", diff --git a/notebooks/22_DLC_Loop.ipynb b/notebooks/22_DLC_Loop.ipynb index 19fadd24f..103b39525 100644 --- a/notebooks/22_DLC_Loop.ipynb +++ b/notebooks/22_DLC_Loop.ipynb @@ -118,13 +118,10 @@ "source": [ "import os\n", "import datajoint as dj\n", - "from pprint import pprint\n", "\n", "import spyglass.common as sgc\n", "import spyglass.position.v1 as sgp\n", "\n", - "from pathlib import Path, PosixPath, PurePath\n", - "import glob\n", "import numpy as np\n", "import pandas as pd\n", "import pynwb\n", diff --git a/notebooks/41_Extracting_Clusterless_Waveform_Features.ipynb b/notebooks/41_Extracting_Clusterless_Waveform_Features.ipynb index 2c1fc739f..09cc22bb2 100644 --- a/notebooks/41_Extracting_Clusterless_Waveform_Features.ipynb +++ b/notebooks/41_Extracting_Clusterless_Waveform_Features.ipynb @@ -298,7 +298,7 @@ "metadata": {}, "outputs": [], "source": [ - "from spyglass.spikesorting.merge import SpikeSortingOutput\n", + "from spyglass.spikesorting.spikesorting_merge import SpikeSortingOutput\n", "\n", "sorting_ids = (\n", " sgs.SpikeSortingSelection & {\"nwb_file_name\": nwb_copy_file_name}\n", @@ -657,7 +657,7 @@ } ], "source": [ - "from spyglass.spikesorting.merge import SpikeSortingOutput\n", + "from spyglass.spikesorting.spikesorting_merge import SpikeSortingOutput\n", "\n", "merge_ids = (\n", " (SpikeSortingOutput.CurationV1 * sgs.SpikeSortingSelection)\n", diff --git a/notebooks/42_Decoding_Clusterless.ipynb b/notebooks/42_Decoding_Clusterless.ipynb index 5c4ffd11e..c0dbdbace 100644 --- a/notebooks/42_Decoding_Clusterless.ipynb +++ b/notebooks/42_Decoding_Clusterless.ipynb @@ -59,8 +59,9 @@ "name": "stderr", "output_type": "stream", "text": [ - "[2024-01-17 22:43:09,216][INFO]: Connecting root@localhost:3306\n", - "[2024-01-17 22:43:09,293][INFO]: Connected root@localhost:3306\n" + "[2024-01-29 10:24:06,266][INFO]: Connecting root@localhost:3306\n", + "[2024-01-29 10:24:06,337][INFO]: Connected root@localhost:3306\n", + "[10:24:07][WARNING] Spyglass: Please update position_tools to >= 0.1.0\n" ] }, { @@ -276,7 +277,7 @@ } ], "source": [ - "from spyglass.spikesorting.merge import SpikeSortingOutput\n", + "from spyglass.spikesorting.spikesorting_merge import SpikeSortingOutput\n", "import spyglass.spikesorting.v1 as sgs\n", "from spyglass.decoding.v1.waveform_features import UnitWaveformFeaturesSelection\n", "\n", @@ -712,6 +713,39 @@ "execution_count": 6, "metadata": {}, "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/Users/edeno/miniconda3/envs/spyglass/lib/python3.9/site-packages/pynwb/ecephys.py:90: UserWarning: ElectricalSeries 'e-series': The second dimension of data does not match the length of electrodes. Your data may be transposed.\n", + " warnings.warn(\"%s '%s': The second dimension of data does not match the length of electrodes. \"\n", + "/Users/edeno/miniconda3/envs/spyglass/lib/python3.9/site-packages/pynwb/base.py:193: UserWarning: TimeSeries 'analog': Length of data does not match length of timestamps. Your data may be transposed. Time should be on the 0th dimension\n", + " warn(\"%s '%s': Length of data does not match length of timestamps. Your data may be transposed. \"\n", + "[10:24:13][INFO] Spyglass: Writing new NWB file mediumnwb20230802_FUSH604NQA.nwb\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Computing position for: {'nwb_file_name': 'mediumnwb20230802_.nwb', 'interval_list_name': 'pos 0 valid times', 'trodes_pos_params_name': 'default_decoding'}\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[2024-01-29 10:24:13,819][WARNING]: Skipped checksum for file with hash: f05fc782-7d7e-7835-5aef-bc4f5837358b, and path: /Users/edeno/Documents/GitHub/spyglass/DATA/raw/mediumnwb20230802_.nwb\n", + "[2024-01-29 10:24:13,821][WARNING]: Skipped checksum for file with hash: f05fc782-7d7e-7835-5aef-bc4f5837358b, and path: /Users/edeno/Documents/GitHub/spyglass/DATA/raw/mediumnwb20230802_.nwb\n", + "/Users/edeno/miniconda3/envs/spyglass/lib/python3.9/site-packages/pynwb/ecephys.py:90: UserWarning: ElectricalSeries 'e-series': The second dimension of data does not match the length of electrodes. Your data may be transposed.\n", + " warnings.warn(\"%s '%s': The second dimension of data does not match the length of electrodes. \"\n", + "/Users/edeno/miniconda3/envs/spyglass/lib/python3.9/site-packages/pynwb/base.py:193: UserWarning: TimeSeries 'analog': Length of data does not match length of timestamps. Your data may be transposed. Time should be on the 0th dimension\n", + " warn(\"%s '%s': Length of data does not match length of timestamps. Your data may be transposed. \"\n", + "[2024-01-29 10:24:13,996][WARNING]: Skipped checksum for file with hash: f05fc782-7d7e-7835-5aef-bc4f5837358b, and path: /Users/edeno/Documents/GitHub/spyglass/DATA/raw/mediumnwb20230802_.nwb\n", + "[2024-01-29 10:24:13,998][WARNING]: Skipped checksum for file with hash: f05fc782-7d7e-7835-5aef-bc4f5837358b, and path: /Users/edeno/Documents/GitHub/spyglass/DATA/raw/mediumnwb20230802_.nwb\n", + "[10:24:14][INFO] Spyglass: No video frame index found. Assuming all camera frames are present.\n" + ] + }, { "data": { "text/html": [ @@ -783,10 +817,10 @@ "

trodes_pos_params_name

\n", " name for this set of parameters\n", " \n", - " a95d0105-de87-9c2f-85cf-f940e0490bee\n", + " 6dfae23d-6034-e483-06e7-28ab4c29282f\n", "mediumnwb20230802_.nwb\n", "pos 0 valid times\n", - "default \n", + "default_decoding \n", " \n", " \n", "

Total: 1

\n", @@ -795,7 +829,7 @@ "text/plain": [ "*merge_id nwb_file_name interval_list_ trodes_pos_par\n", "+------------+ +------------+ +------------+ +------------+\n", - "a95d0105-de87- mediumnwb20230 pos 0 valid ti default \n", + "6dfae23d-6034- mediumnwb20230 pos 0 valid ti default_decodi\n", " (Total: 1)" ] }, @@ -806,8 +840,39 @@ ], "source": [ "from spyglass.position import PositionOutput\n", + "import spyglass.position as sgp\n", "\n", - "PositionOutput.TrodesPosV1 & {\"nwb_file_name\": nwb_copy_file_name}" + "\n", + "sgp.v1.TrodesPosParams.insert1(\n", + " {\n", + " \"trodes_pos_params_name\": \"default_decoding\",\n", + " \"params\": {\n", + " \"max_LED_separation\": 9.0,\n", + " \"max_plausible_speed\": 300.0,\n", + " \"position_smoothing_duration\": 0.125,\n", + " \"speed_smoothing_std_dev\": 0.100,\n", + " \"orient_smoothing_std_dev\": 0.001,\n", + " \"led1_is_front\": 1,\n", + " \"is_upsampled\": 1,\n", + " \"upsampling_sampling_rate\": 250,\n", + " \"upsampling_interpolation_method\": \"linear\",\n", + " },\n", + " },\n", + " skip_duplicates=True,\n", + ")\n", + "\n", + "trodes_s_key = {\n", + " \"nwb_file_name\": nwb_copy_file_name,\n", + " \"interval_list_name\": \"pos 0 valid times\",\n", + " \"trodes_pos_params_name\": \"default_decoding\",\n", + "}\n", + "sgp.v1.TrodesPosSelection.insert1(\n", + " trodes_s_key,\n", + " skip_duplicates=True,\n", + ")\n", + "sgp.v1.TrodesPosV1.populate(trodes_s_key)\n", + "\n", + "PositionOutput.TrodesPosV1 & trodes_s_key" ] }, { @@ -911,7 +976,7 @@ " & {\n", " \"nwb_file_name\": nwb_copy_file_name,\n", " \"interval_list_name\": \"pos 0 valid times\",\n", - " \"trodes_pos_params_name\": \"default\",\n", + " \"trodes_pos_params_name\": \"default_decoding\",\n", " }\n", ").fetch(\"merge_id\")\n", "\n", @@ -1025,7 +1090,7 @@ " \n", " mediumnwb20230802_.nwb\n", "test_group\n", - "a95d0105-de87-9c2f-85cf-f940e0490bee \n", + "6dfae23d-6034-e483-06e7-28ab4c29282f \n", " \n", " \n", "

Total: 1

\n", @@ -1034,7 +1099,7 @@ "text/plain": [ "*nwb_file_name *position_grou *pos_merge_id \n", "+------------+ +------------+ +------------+\n", - "mediumnwb20230 test_group a95d0105-de87-\n", + "mediumnwb20230 test_group 6dfae23d-6034-\n", " (Total: 1)" ] }, @@ -1579,23 +1644,17 @@ "

estimate_decoding_params

\n", " whether to estimate the decoding parameters\n", " \n", - " mediumnwb20230802_.nwb\n", - "test_group\n", - "test_group\n", - "contfrag_clusterless\n", - "pos 0 valid times\n", - "test decoding interval\n", - "0 \n", + " \n", " \n", " \n", - "

Total: 1

\n", + "

Total: 0

\n", " " ], "text/plain": [ "*nwb_file_name *waveform_feat *position_grou *decoding_para *encoding_inte *decoding_inte *estimate_deco\n", "+------------+ +------------+ +------------+ +------------+ +------------+ +------------+ +------------+\n", - "mediumnwb20230 test_group test_group contfrag_clust pos 0 valid ti test decoding 0 \n", - " (Total: 1)" + "\n", + " (Total: 0)" ] }, "execution_count": 15, @@ -2036,7 +2095,77 @@ "cell_type": "code", "execution_count": 20, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:24:17][WARNING] Spyglass: Upsampled position data, frame indices are invalid. Setting add_frame_ind=False\n", + "[2024-01-29 10:24:17,234][WARNING]: Skipped checksum for file with hash: 0cd40383-03e0-44ec-5dac-36c66063796a, and path: /Users/edeno/Documents/GitHub/spyglass/DATA/analysis/mediumnwb20230802/mediumnwb20230802_FUSH604NQA.nwb\n", + "[2024-01-29 10:24:17,409][WARNING]: Skipped checksum for file with hash: a7c9b1d9-d1a2-7f40-9127-206e83a87006, and path: /Users/edeno/Documents/GitHub/spyglass/DATA/analysis/mediumnwb20230802/mediumnwb20230802_NQEPSMKPK0.nwb\n", + "[2024-01-29 10:24:17,411][WARNING]: Skipped checksum for file with hash: ec7faa5b-3847-6649-1a93-74ebd50dcfb9, and path: /Users/edeno/Documents/GitHub/spyglass/DATA/analysis/mediumnwb20230802/mediumnwb20230802_F02UG5Z5FR.nwb\n", + "[2024-01-29 10:24:17,413][WARNING]: Skipped checksum for file with hash: 8e964932-96ab-e1c9-2133-edce8eacab5f, and path: /Users/edeno/Documents/GitHub/spyglass/DATA/analysis/mediumnwb20230802/mediumnwb20230802_OTV91MLKDT.nwb\n", + "[2024-01-29 10:24:17,415][WARNING]: Skipped checksum for file with hash: 895bac7b-bfd6-b4f2-b2ad-460362aaafa8, and path: /Users/edeno/Documents/GitHub/spyglass/DATA/analysis/mediumnwb20230802/mediumnwb20230802_TSPNTCGNN1.nwb\n", + "[2024-01-29 10:24:17,417][WARNING]: Skipped checksum for file with hash: 58713583-cf49-4527-7707-105f9c9ee477, and path: /Users/edeno/Documents/GitHub/spyglass/DATA/analysis/mediumnwb20230802/mediumnwb20230802_QSK70WFDJH.nwb\n", + "[2024-01-29 10:24:17,419][WARNING]: Skipped checksum for file with hash: a64829f8-ab12-fecc-eda9-a22b90b20d43, and path: /Users/edeno/Documents/GitHub/spyglass/DATA/analysis/mediumnwb20230802/mediumnwb20230802_DO45HKXYTB.nwb\n", + "[2024-01-29 10:24:17,420][WARNING]: Skipped checksum for file with hash: 3a580271-9126-8e57-048e-a7bbb3f917b9, and path: /Users/edeno/Documents/GitHub/spyglass/DATA/analysis/mediumnwb20230802/mediumnwb20230802_KFIYRJ4HFO.nwb\n", + "[2024-01-29 10:24:17,423][WARNING]: Skipped checksum for file with hash: 13cf8ad9-023c-c9b7-05c3-eaa3330304f2, and path: /Users/edeno/Documents/GitHub/spyglass/DATA/analysis/mediumnwb20230802/mediumnwb20230802_0YIM5K3H47.nwb\n", + "[2024-01-29 10:24:17,425][WARNING]: Skipped checksum for file with hash: 7ce8a640-0a25-4866-6d5a-aa2c65f0aca5, and path: /Users/edeno/Documents/GitHub/spyglass/DATA/analysis/mediumnwb20230802/mediumnwb20230802_CTLEGE2TWZ.nwb\n", + "[2024-01-29 10:24:17,427][WARNING]: Skipped checksum for file with hash: aa657f4f-f409-d444-8b32-31d37abe0797, and path: /Users/edeno/Documents/GitHub/spyglass/DATA/analysis/mediumnwb20230802/mediumnwb20230802_7EN0N1U4U1.nwb\n", + "[2024-01-29 10:24:17,429][WARNING]: Skipped checksum for file with hash: f3b4bd22-1439-e6d2-4e15-aa3650143fdf, and path: /Users/edeno/Documents/GitHub/spyglass/DATA/analysis/mediumnwb20230802/mediumnwb20230802_DHKWBWWAMC.nwb\n", + "[2024-01-29 10:24:17,430][WARNING]: Skipped checksum for file with hash: 68eac0b2-e5be-e0c5-9eae-cd8dbe6676a8, and path: /Users/edeno/Documents/GitHub/spyglass/DATA/analysis/mediumnwb20230802/mediumnwb20230802_PEN0D79Q0B.nwb\n", + "[2024-01-29 10:24:17,432][WARNING]: Skipped checksum for file with hash: c8b95099-2cb3-df0b-5ab1-7a5e120a8e2f, and path: /Users/edeno/Documents/GitHub/spyglass/DATA/analysis/mediumnwb20230802/mediumnwb20230802_WP7SIXDJ2A.nwb\n", + "[2024-01-29 10:24:17,434][WARNING]: Skipped checksum for file with hash: 8fae8089-f683-5f0a-4e59-c71d6ee14f38, and path: /Users/edeno/Documents/GitHub/spyglass/DATA/analysis/mediumnwb20230802/mediumnwb20230802_B82OS6W1QA.nwb\n", + "[2024-01-29 10:24:17,437][WARNING]: Skipped checksum for file with hash: dd9d0f51-6445-b368-32bd-b1f142bf6ed3, and path: /Users/edeno/Documents/GitHub/spyglass/DATA/analysis/mediumnwb20230802/mediumnwb20230802_XO17FQLN6T.nwb\n", + "[2024-01-29 10:24:17,439][WARNING]: Skipped checksum for file with hash: 4e2cf5f5-ff7c-1a2b-db85-2d1c4f036fbd, and path: /Users/edeno/Documents/GitHub/spyglass/DATA/analysis/mediumnwb20230802/mediumnwb20230802_OCFI0GFLZ9.nwb\n", + "[2024-01-29 10:24:17,441][WARNING]: Skipped checksum for file with hash: 8691c252-0bd1-122b-8cf3-b89c4d0fdee0, and path: /Users/edeno/Documents/GitHub/spyglass/DATA/analysis/mediumnwb20230802/mediumnwb20230802_60M9VSZX0W.nwb\n", + "[2024-01-29 10:24:17,443][WARNING]: Skipped checksum for file with hash: 57b89835-8edb-e91d-0798-09d22fb4fbc9, and path: /Users/edeno/Documents/GitHub/spyglass/DATA/analysis/mediumnwb20230802/mediumnwb20230802_Z5HJ68LHYW.nwb\n", + "[2024-01-29 10:24:17,445][WARNING]: Skipped checksum for file with hash: 54401121-4426-86c9-72f7-e056bc16e99d, and path: /Users/edeno/Documents/GitHub/spyglass/DATA/analysis/mediumnwb20230802/mediumnwb20230802_U5U5JVGY4F.nwb\n", + "[2024-01-29 10:24:17,447][WARNING]: Skipped checksum for file with hash: 0ff21e84-2214-6911-2575-a9c92a541407, and path: /Users/edeno/Documents/GitHub/spyglass/DATA/analysis/mediumnwb20230802/mediumnwb20230802_0D5Z0NSIP8.nwb\n", + "[2024-01-29 10:24:17,449][WARNING]: Skipped checksum for file with hash: 0949b006-5309-93c8-fd8b-1308e8130869, and path: /Users/edeno/Documents/GitHub/spyglass/DATA/analysis/mediumnwb20230802/mediumnwb20230802_EYV2NARUKU.nwb\n", + "[2024-01-29 10:24:17,451][WARNING]: Skipped checksum for file with hash: b4b31e50-dfa2-0d02-514a-525782a81255, and path: /Users/edeno/Documents/GitHub/spyglass/DATA/analysis/mediumnwb20230802/mediumnwb20230802_T4XBCIW44T.nwb\n", + "[2024-01-29 10:24:17,453][WARNING]: Skipped checksum for file with hash: c18a9ac4-06bc-4249-2bad-439d4f618421, and path: /Users/edeno/Documents/GitHub/spyglass/DATA/analysis/mediumnwb20230802/mediumnwb20230802_UD55CR8LZK.nwb\n" + ] + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "0d8469b4cf60446fb7d60e53b61bf97f", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Encoding models: 0%| | 0/23 [00:00
<xarray.Dataset>\n",
-       "Dimensions:                      (state_ind: 26668, dim_0: 26668, time: 451,\n",
+       "Dimensions:                      (state_ind: 26668, dim_0: 26668, time: 3750,\n",
        "                                  states: 2, intervals: 1, state_bins: 26668)\n",
        "Coordinates:\n",
        "  * state_ind                    (state_ind) int32 0 0 0 0 0 0 0 ... 1 1 1 1 1 1\n",
@@ -2570,7 +2699,7 @@
        "  * state_bins                   (state_bins) object MultiIndex\n",
        "  * state                        (state_bins) object 'Continuous' ... 'Fragme...\n",
        "  * x_position                   (state_bins) float64 29.02 29.02 ... 262.7\n",
-       "  * y_position                   (state_bins) float64 0.4493 2.445 ... 224.0\n",
+       "  * y_position                   (state_bins) float64 0.5211 2.516 ... 224.0\n",
        "Dimensions without coordinates: dim_0, intervals\n",
        "Data variables:\n",
        "    initial_conditions           (dim_0) float64 ...\n",
@@ -2578,53 +2707,53 @@
        "    acausal_posterior            (intervals, time, state_bins) float32 ...\n",
        "    acausal_state_probabilities  (intervals, time, states) float64 ...\n",
        "Attributes:\n",
-       "    marginal_log_likelihoods:  -154947.16
  • marginal_log_likelihoods :
    -159596.89
  • " ], "text/plain": [ "\n", - "Dimensions: (state_ind: 26668, dim_0: 26668, time: 451,\n", + "Dimensions: (state_ind: 26668, dim_0: 26668, time: 3750,\n", " states: 2, intervals: 1, state_bins: 26668)\n", "Coordinates:\n", " * state_ind (state_ind) int32 0 0 0 0 0 0 0 ... 1 1 1 1 1 1\n", @@ -2635,7 +2764,7 @@ " * state_bins (state_bins) object MultiIndex\n", " * state (state_bins) object 'Continuous' ... 'Fragme...\n", " * x_position (state_bins) float64 29.02 29.02 ... 262.7\n", - " * y_position (state_bins) float64 0.4493 2.445 ... 224.0\n", + " * y_position (state_bins) float64 0.5211 2.516 ... 224.0\n", "Dimensions without coordinates: dim_0, intervals\n", "Data variables:\n", " initial_conditions (dim_0) float64 ...\n", @@ -2643,7 +2772,7 @@ " acausal_posterior (intervals, time, state_bins) float32 ...\n", " acausal_state_probabilities (intervals, time, states) float64 ...\n", "Attributes:\n", - " marginal_log_likelihoods: -154947.16" + " marginal_log_likelihoods: -159596.89" ] }, "execution_count": 22, @@ -2652,7 +2781,7 @@ } ], "source": [ - "decoding_results = (ClusterlessDecodingV1 & selection_key).load_results()\n", + "decoding_results = (ClusterlessDecodingV1 & selection_key).fetch_results()\n", "decoding_results" ] }, @@ -2672,9 +2801,13 @@ "name": "stderr", "output_type": "stream", "text": [ - "[22:43:13][INFO] Spyglass: Cleaning up decoding outputs\n", - "[2024-01-17 22:43:13,623][WARNING]: Skipped checksum for file with hash: ecf01dd1-0d3b-24c2-b843-7e554abf0ea7, and path: /Users/edeno/Documents/GitHub/spyglass/DATA/analysis/mediumnwb20230802/mediumnwb20230802_a26e1d1a-1480-4f89-b5e0-bb6486d7d15e.nc\n", - "[2024-01-17 22:43:13,713][WARNING]: Skipped checksum for file with hash: 257962d6-fc68-dc91-b0d2-8bef2a4914f3, and path: /Users/edeno/Documents/GitHub/spyglass/DATA/analysis/mediumnwb20230802/mediumnwb20230802_a26e1d1a-1480-4f89-b5e0-bb6486d7d15e.pkl\n" + "[10:26:49][INFO] Spyglass: Cleaning up decoding outputs\n", + "[2024-01-29 10:26:49,699][WARNING]: Skipped checksum for file with hash: 10c77056-5508-ace0-bd84-5a4d7497f7a9, and path: /Users/edeno/Documents/GitHub/spyglass/DATA/analysis/mediumnwb20230802/mediumnwb20230802_c17fbf1c-67bd-4d5e-b179-83f501713b9c.nc\n", + "[10:26:49][INFO] Spyglass: Removing /Users/edeno/Documents/GitHub/spyglass/DATA/analysis/mediumnwb20230802/mediumnwb20230802_259e8498-1eb6-4e84-a0f6-7575c4ab9b87.nc\n", + "[10:26:49][INFO] Spyglass: Removing /Users/edeno/Documents/GitHub/spyglass/DATA/analysis/mediumnwb20230802/mediumnwb20230802_8404dc49-081c-48c7-b448-34767512e8ed.nc\n", + "[2024-01-29 10:26:49,774][WARNING]: Skipped checksum for file with hash: c4a577dc-6f11-bd71-cc5f-e131c6eaa39f, and path: /Users/edeno/Documents/GitHub/spyglass/DATA/analysis/mediumnwb20230802/mediumnwb20230802_c17fbf1c-67bd-4d5e-b179-83f501713b9c.pkl\n", + "[10:26:49][INFO] Spyglass: Removing /Users/edeno/Documents/GitHub/spyglass/DATA/analysis/mediumnwb20230802/mediumnwb20230802_259e8498-1eb6-4e84-a0f6-7575c4ab9b87.pkl\n", + "[10:26:49][INFO] Spyglass: Removing /Users/edeno/Documents/GitHub/spyglass/DATA/analysis/mediumnwb20230802/mediumnwb20230802_8404dc49-081c-48c7-b448-34767512e8ed.pkl\n" ] } ], @@ -2710,12 +2843,12 @@ "# (\n", "# position_info,\n", "# position_variable_names,\n", - "# ) = ClusterlessDecodingV1.load_position_info(selection_key)\n", + "# ) = ClusterlessDecodingV1.fetch_position_info(selection_key)\n", "# results_time = decoding_results.acausal_posterior.isel(intervals=0).time.values\n", "# position_info = position_info.loc[results_time[0] : results_time[-1]]\n", "\n", - "# env = ClusterlessDecodingV1.load_environments(selection_key)[0]\n", - "# spike_times, _ = ClusterlessDecodingV1.load_spike_data(selection_key)\n", + "# env = ClusterlessDecodingV1.fetch_environments(selection_key)[0]\n", + "# spike_times, _ = ClusterlessDecodingV1.fetch_spike_data(selection_key)\n", "\n", "\n", "# create_interactive_2D_decoding_figurl(\n", diff --git a/notebooks/43_Decoding_SortedSpikes.ipynb b/notebooks/43_Decoding_SortedSpikes.ipynb index 4911824e6..9bbd01592 100644 --- a/notebooks/43_Decoding_SortedSpikes.ipynb +++ b/notebooks/43_Decoding_SortedSpikes.ipynb @@ -16,14 +16,12 @@ "- `decoding_interval`\n", "\n", "This time, instead of extracting waveform features, we can proceed directly from the SpikeSortingOutput table to specify which units we want to decode. The rest of the decoding process is the same as before.\n", - "\n", - "\n", - "## SortedSpikesGroup" + "\n" ] }, { "cell_type": "code", - "execution_count": 1, + "execution_count": 9, "metadata": {}, "outputs": [], "source": [ @@ -35,19 +33,158 @@ ") # load config for database connection info" ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## SortedSpikesGroup\n", + "\n", + "`SortedSpikesGroup` is a child table of `SpikeSortingOutput` in the spikesorting pipeline. It allows us to group the spikesorting results from multiple \n", + "sources (e.g. multiple terode groups or intervals) into a single entry. Here we will group together the spiking of multiple tetrode groups to use for decoding.\n", + "\n", + "\n", + "This table allows us filter units by their annotation labels from curation (e.g only include units labeled \"good\", exclude units labeled \"noise\") by defining parameters from `UnitSelectionParams`. When accessing data through `SortedSpikesGroup` the table will include only units with at least one label in `include_labels` and no labels in `exclude_labels`. We can look at those here:\n" + ] + }, { "cell_type": "code", - "execution_count": 2, + "execution_count": 1, "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ - "[2024-01-17 22:49:07,284][INFO]: Connecting root@localhost:3306\n", - "[2024-01-17 22:49:07,353][INFO]: Connected root@localhost:3306\n" + "[2024-02-02 12:06:04,725][INFO]: Connecting sambray@lmf-db.cin.ucsf.edu:3306\n", + "[2024-02-02 12:06:04,762][INFO]: Connected sambray@lmf-db.cin.ucsf.edu:3306\n", + "[12:06:05][WARNING] Spyglass: Please update position_tools to >= 0.1.0\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "{'unit_filter_params_name': 'default_exclusion', 'include_labels': [], 'exclude_labels': ['noise', 'mua']}\n" ] }, + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + "
    \n", + " \n", + " \n", + " \n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "
    \n", + "

    unit_filter_params_name

    \n", + " \n", + "
    \n", + "

    include_labels

    \n", + " \n", + "
    \n", + "

    exclude_labels

    \n", + " \n", + "
    all_units=BLOB==BLOB=
    default_exclusion=BLOB==BLOB=
    exclude_noise=BLOB==BLOB=
    \n", + " \n", + "

    Total: 3

    \n", + " " + ], + "text/plain": [ + "*unit_filter_p include_la exclude_la\n", + "+------------+ +--------+ +--------+\n", + "all_units =BLOB= =BLOB= \n", + "default_exclus =BLOB= =BLOB= \n", + "exclude_noise =BLOB= =BLOB= \n", + " (Total: 3)" + ] + }, + "execution_count": 1, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "from spyglass.spikesorting.analysis.v1.group import UnitSelectionParams\n", + "UnitSelectionParams().insert_default()\n", + "\n", + "# look at the filter set we'll use here\n", + "unit_filter_params_name = \"default_exclusion\"\n", + "print((UnitSelectionParams()\n", + " & {\"unit_filter_params_name\":unit_filter_params_name}).fetch1())\n", + "# look at full table\n", + "UnitSelectionParams()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now we can make our sorted spikes group with this unit selection parameter" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [ { "data": { "text/html": [ @@ -131,113 +268,40 @@ "

    curation_id

    \n", " \n", " \n", - " 08a302b6-5505-40fa-b4d5-62162f8eef58\n", - "485a4ddf-332d-35b5-3ad4-0561736c1844\n", - "449b64e3-db0b-437e-a1b9-0d29928aa2dd\n", - "clusterless_thresholder\n", - "default_clusterless\n", - "mediumnwb20230802_.nwb\n", - "45f6b9a1-eef3-46eb-866d-d0999afebda6\n", - "00ca508ee-af4c-4a89-8181-d48bd209bfd4\n", - "6acb99b8-6a0c-eb83-1141-5f603c5895e0\n", - "328da21c-1d9c-41e2-9800-76b3484b707b\n", - "clusterless_thresholder\n", - "default_clusterless\n", - "mediumnwb20230802_.nwb\n", - "686d9951-1c0f-4d5e-9f5c-09e6fd8bdd4c\n", - "0209dc048-6fae-4315-b293-c06fff29f947\n", - "f7237e18-4e73-4aee-805b-90735e9147de\n", - "aff78f2f-2ba0-412a-95cc-447c3a2f4683\n", - "clusterless_thresholder\n", - "default_clusterless\n", - "mediumnwb20230802_.nwb\n", - "719e8a86-fcf1-4ffc-8c1f-ea912f67ad5d\n", - "021a9a593-f6f3-4b82-99d7-8fc46556eff3\n", - "7e3fa66e-727e-1541-819a-b01309bb30ae\n", - "2402805a-04f9-4a88-9ccf-071376c8de19\n", - "clusterless_thresholder\n", - "default_clusterless\n", - "mediumnwb20230802_.nwb\n", - "d581b117-160e-4311-b096-7781a4de4394\n", - "0406a20e3-5a9f-4fec-b046-a6561f72461e\n", - "6d039a63-17ad-0b78-4b1e-f02d5f3dbbc5\n", - "f1427e00-2974-4301-b2ac-b4dc29277c51\n", - "clusterless_thresholder\n", - "default_clusterless\n", - "mediumnwb20230802_.nwb\n", - "0e848c38-9105-4ea4-b6ba-dbdd5b46a088\n", - "04131c51b-c56d-41fa-b046-46635fc17fd9\n", - "e0e9133a-7a4e-1321-a43a-e8afcb2f25da\n", - "9e332d82-1daf-4e92-bb50-12e4f9430875\n", - "clusterless_thresholder\n", - "default_clusterless\n", - "mediumnwb20230802_.nwb\n", - "9ed11db5-c42e-491a-8caf-7d9a37a65f13\n", - "04c5a629a-71d9-481d-ab11-a4cb0fc16087\n", - "9959b614-2318-f597-6651-a3a82124d28a\n", - "3a2c3eed-413a-452a-83c8-0e4648141bde\n", - "clusterless_thresholder\n", - "default_clusterless\n", - "mediumnwb20230802_.nwb\n", - "2b9fbf14-74a0-4294-a805-26702340aac9\n", - "04d629c07-1931-4e1f-a3a8-cbf1b72161e3\n", - "c0eb6455-fc41-c200-b62e-e3ca81b9a3f7\n", - "f07bc0b0-de6b-4424-8ef9-766213aaca26\n", - "clusterless_thresholder\n", - "default_clusterless\n", - "mediumnwb20230802_.nwb\n", - "5c68f0f0-f577-4905-8a09-e4d171d0a22d\n", - "0554a9a3c-0461-48be-8435-123eed59c228\n", - "912e250e-56d8-ee33-4525-c844d810971b\n", - "7f128981-6868-4976-ba20-248655dcac21\n", - "clusterless_thresholder\n", - "default_clusterless\n", + " 642242ff-5f0e-45a2-bcc1-ca681f37b4a3\n", + "75286bf3-f876-4550-f235-321f2a7badef\n", + "01c5b8e9-933d-4f1e-9a5d-c494276edb3a\n", + "mountainsort4\n", + "franklab_tetrode_hippocampus_30KHz\n", "mediumnwb20230802_.nwb\n", - "f4b9301f-bc91-455b-9474-c801093f3856\n", - "07bb007f2-26d3-463f-b7dc-7bd4d271725e\n", - "d7d2c97a-0e6e-d1b8-735c-d55dc66a30e1\n", - "a9b7cec0-1256-49cf-abf0-8c45fd155379\n", - "clusterless_thresholder\n", - "default_clusterless\n", + "0a6611b3-c593-4900-a715-66bb1396940e\n", + "1a4b5a94d-ba41-4634-92d0-1d31c9daa913\n", + "143dff79-3779-c0d2-46fe-7c5040404219\n", + "a8a1d29d-ffdf-4370-8b3d-909fef57f9d4\n", + "mountainsort4\n", + "franklab_tetrode_hippocampus_30KHz\n", "mediumnwb20230802_.nwb\n", - "74270cba-36ee-4afb-ab50-2a6cc948e68c\n", - "080e1f37f-48a7-4087-bd37-7a37b6a2c160\n", - "abb92dce-4410-8f17-a501-a4104bda0dcf\n", - "3c40ebdc-0b61-4105-9971-e1348bd49bc7\n", - "clusterless_thresholder\n", - "default_clusterless\n", + "3d782852-a56b-4a9d-89ca-be9e1a15c957\n", + "1874775be-df0f-4850-8f88-59ba1bbead89\n", + "a900c1c8-909d-e583-c377-e98c4f0deebf\n", + "747f4eea-6df3-422b-941e-b5aaad7ec607\n", + "mountainsort4\n", + "franklab_tetrode_hippocampus_30KHz\n", "mediumnwb20230802_.nwb\n", - "0f91197e-bebb-4dc6-ad41-5bf89c3eed28\n", - "08848c4a8-a2f2-4f3d-82cd-51b13b8bae3c\n", - "74e10781-1228-4075-0870-af224024ffdc\n", - "257c077b-8f3b-4abb-a631-6b8084d6a1ea\n", - "clusterless_thresholder\n", - "default_clusterless\n", - "mediumnwb20230802_.nwb\n", - "e289e03d-32ad-461a-a1cc-c88537343149\n", - "0 \n", + "9cf9e3cd-7115-4b59-a718-3633725d4738\n", + "1 \n", " \n", - "

    ...

    \n", - "

    Total: 23

    \n", + " \n", + "

    Total: 3

    \n", " " ], "text/plain": [ "*sorting_id *merge_id recording_id sorter sorter_param_n nwb_file_name interval_list_ curation_id \n", "+------------+ +------------+ +------------+ +------------+ +------------+ +------------+ +------------+ +------------+\n", - "08a302b6-5505- 485a4ddf-332d- 449b64e3-db0b- clusterless_th default_cluste mediumnwb20230 45f6b9a1-eef3- 0 \n", - "0ca508ee-af4c- 6acb99b8-6a0c- 328da21c-1d9c- clusterless_th default_cluste mediumnwb20230 686d9951-1c0f- 0 \n", - "209dc048-6fae- f7237e18-4e73- aff78f2f-2ba0- clusterless_th default_cluste mediumnwb20230 719e8a86-fcf1- 0 \n", - "21a9a593-f6f3- 7e3fa66e-727e- 2402805a-04f9- clusterless_th default_cluste mediumnwb20230 d581b117-160e- 0 \n", - "406a20e3-5a9f- 6d039a63-17ad- f1427e00-2974- clusterless_th default_cluste mediumnwb20230 0e848c38-9105- 0 \n", - "4131c51b-c56d- e0e9133a-7a4e- 9e332d82-1daf- clusterless_th default_cluste mediumnwb20230 9ed11db5-c42e- 0 \n", - "4c5a629a-71d9- 9959b614-2318- 3a2c3eed-413a- clusterless_th default_cluste mediumnwb20230 2b9fbf14-74a0- 0 \n", - "4d629c07-1931- c0eb6455-fc41- f07bc0b0-de6b- clusterless_th default_cluste mediumnwb20230 5c68f0f0-f577- 0 \n", - "554a9a3c-0461- 912e250e-56d8- 7f128981-6868- clusterless_th default_cluste mediumnwb20230 f4b9301f-bc91- 0 \n", - "7bb007f2-26d3- d7d2c97a-0e6e- a9b7cec0-1256- clusterless_th default_cluste mediumnwb20230 74270cba-36ee- 0 \n", - "80e1f37f-48a7- abb92dce-4410- 3c40ebdc-0b61- clusterless_th default_cluste mediumnwb20230 0f91197e-bebb- 0 \n", - "8848c4a8-a2f2- 74e10781-1228- 257c077b-8f3b- clusterless_th default_cluste mediumnwb20230 e289e03d-32ad- 0 \n", - " ...\n", - " (Total: 23)" + "642242ff-5f0e- 75286bf3-f876- 01c5b8e9-933d- mountainsort4 franklab_tetro mediumnwb20230 0a6611b3-c593- 1 \n", + "a4b5a94d-ba41- 143dff79-3779- a8a1d29d-ffdf- mountainsort4 franklab_tetro mediumnwb20230 3d782852-a56b- 1 \n", + "874775be-df0f- a900c1c8-909d- 747f4eea-6df3- mountainsort4 franklab_tetro mediumnwb20230 9cf9e3cd-7115- 1 \n", + " (Total: 3)" ] }, "execution_count": 2, @@ -246,70 +310,23 @@ } ], "source": [ - "from spyglass.spikesorting.merge import SpikeSortingOutput\n", + "from spyglass.spikesorting.spikesorting_merge import SpikeSortingOutput\n", "import spyglass.spikesorting.v1 as sgs\n", "\n", - "\n", "nwb_copy_file_name = \"mediumnwb20230802_.nwb\"\n", "\n", "sorter_keys = {\n", " \"nwb_file_name\": nwb_copy_file_name,\n", - " \"sorter\": \"clusterless_thresholder\",\n", - " \"sorter_param_name\": \"default_clusterless\",\n", + " \"sorter\": \"mountainsort4\",\n", + " \"curation_id\": 1\n", "}\n", - "\n", + "# check the set of sorting we'll use\n", "(sgs.SpikeSortingSelection & sorter_keys) * SpikeSortingOutput.CurationV1" ] }, { "cell_type": "code", - "execution_count": 3, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "array([UUID('485a4ddf-332d-35b5-3ad4-0561736c1844'),\n", - " UUID('6acb99b8-6a0c-eb83-1141-5f603c5895e0'),\n", - " UUID('f7237e18-4e73-4aee-805b-90735e9147de'),\n", - " UUID('7e3fa66e-727e-1541-819a-b01309bb30ae'),\n", - " UUID('6d039a63-17ad-0b78-4b1e-f02d5f3dbbc5'),\n", - " UUID('e0e9133a-7a4e-1321-a43a-e8afcb2f25da'),\n", - " UUID('9959b614-2318-f597-6651-a3a82124d28a'),\n", - " UUID('c0eb6455-fc41-c200-b62e-e3ca81b9a3f7'),\n", - " UUID('912e250e-56d8-ee33-4525-c844d810971b'),\n", - " UUID('d7d2c97a-0e6e-d1b8-735c-d55dc66a30e1'),\n", - " UUID('abb92dce-4410-8f17-a501-a4104bda0dcf'),\n", - " UUID('74e10781-1228-4075-0870-af224024ffdc'),\n", - " UUID('8bbddc0f-d6ae-6260-9400-f884a6e25ae8'),\n", - " UUID('614d796c-0b95-6364-aaa0-b6cb1e7bbb83'),\n", - " UUID('b332482b-e430-169d-8ac0-0a73ce968ed7'),\n", - " UUID('86897349-ff68-ac72-02eb-739dd88936e6'),\n", - " UUID('4a712103-c223-864f-82e0-6c23de79cc14'),\n", - " UUID('cf858380-e8a3-49de-c2a9-1a277e307a68'),\n", - " UUID('cc4ee561-f974-f8e5-0ea4-83185263ac67'),\n", - " UUID('4a72c253-b3ca-8c13-e615-736a7ebff35c'),\n", - " UUID('b92a94d8-ee1e-2097-a81f-5c1e1556ed24'),\n", - " UUID('5c53bd33-d57c-fbba-e0fb-55e0bcb85d03'),\n", - " UUID('0751a1e1-a406-7f87-ae6f-ce4ffc60621c')], dtype=object)" - ] - }, - "execution_count": 3, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "spikesorting_merge_ids = (\n", - " (sgs.SpikeSortingSelection & sorter_keys) * SpikeSortingOutput.CurationV1\n", - ").fetch(\"merge_id\")\n", - "\n", - "spikesorting_merge_ids" - ] - }, - { - "cell_type": "code", - "execution_count": 4, + "execution_count": 6, "metadata": {}, "outputs": [ { @@ -374,10 +391,14 @@ "

    nwb_file_name

    \n", " name of the NWB file\n", "
    \n", + "

    unit_filter_params_name

    \n", + " \n", + "
    \n", "

    sorted_spikes_group_name

    \n", " \n", "
    \n", " mediumnwb20230802_.nwb\n", + "all_units\n", "test_group \n", " \n", " \n", @@ -385,13 +406,13 @@ " " ], "text/plain": [ - "*nwb_file_name *sorted_spikes\n", - "+------------+ +------------+\n", - "mediumnwb20230 test_group \n", + "*nwb_file_name *unit_filter_p *sorted_spikes\n", + "+------------+ +------------+ +------------+\n", + "mediumnwb20230 all_units test_group \n", " (Total: 1)" ] }, - "execution_count": 4, + "execution_count": 6, "metadata": {}, "output_type": "execute_result" } @@ -404,7 +425,7 @@ }, { "cell_type": "code", - "execution_count": 5, + "execution_count": 7, "metadata": {}, "outputs": [ { @@ -469,29 +490,43 @@ "

    nwb_file_name

    \n", " name of the NWB file\n", "
    \n", + "

    unit_filter_params_name

    \n", + " \n", + "
    \n", "

    sorted_spikes_group_name

    \n", " \n", "
    \n", " mediumnwb20230802_.nwb\n", + "all_units\n", + "test_groupmediumnwb20230802_.nwb\n", + "default_exclusion\n", "test_group \n", " \n", " \n", - "

    Total: 1

    \n", + "

    Total: 2

    \n", " " ], "text/plain": [ - "*nwb_file_name *sorted_spikes\n", - "+------------+ +------------+\n", - "mediumnwb20230 test_group \n", - " (Total: 1)" + "*nwb_file_name *unit_filter_p *sorted_spikes\n", + "+------------+ +------------+ +------------+\n", + "mediumnwb20230 all_units test_group \n", + "mediumnwb20230 default_exclus test_group \n", + " (Total: 2)" ] }, - "execution_count": 5, + "execution_count": 7, "metadata": {}, "output_type": "execute_result" } ], "source": [ + "# get the merge_ids for the selected sorting\n", + "spikesorting_merge_ids = (\n", + " (sgs.SpikeSortingSelection & sorter_keys) * SpikeSortingOutput.CurationV1\n", + ").fetch(\"merge_id\")\n", + "\n", + "# create a new sorted spikes group\n", + "unit_filter_params_name = \"default_exclusion\"\n", "SortedSpikesGroup().create_group(\n", " group_name=\"test_group\",\n", " nwb_file_name=nwb_copy_file_name,\n", @@ -499,8 +534,9 @@ " {\"spikesorting_merge_id\": merge_id}\n", " for merge_id in spikesorting_merge_ids\n", " ],\n", + " unit_filter_params_name=unit_filter_params_name,\n", ")\n", - "\n", + "# check the new group\n", "SortedSpikesGroup & {\n", " \"nwb_file_name\": nwb_copy_file_name,\n", " \"sorted_spikes_group_name\": \"test_group\",\n", @@ -509,7 +545,7 @@ }, { "cell_type": "code", - "execution_count": 6, + "execution_count": 8, "metadata": {}, "outputs": [ { @@ -574,6 +610,9 @@ "

    nwb_file_name

    \n", " name of the NWB file\n", "
    \n", + "

    unit_filter_params_name

    \n", + " \n", + "
    \n", "

    sorted_spikes_group_name

    \n", " \n", "
    \n", @@ -581,63 +620,40 @@ " \n", "
    \n", " mediumnwb20230802_.nwb\n", + "default_exclusion\n", "test_group\n", - "0751a1e1-a406-7f87-ae6f-ce4ffc60621cmediumnwb20230802_.nwb\n", - "test_group\n", - "485a4ddf-332d-35b5-3ad4-0561736c1844mediumnwb20230802_.nwb\n", - "test_group\n", - "4a712103-c223-864f-82e0-6c23de79cc14mediumnwb20230802_.nwb\n", + "143dff79-3779-c0d2-46fe-7c5040404219mediumnwb20230802_.nwb\n", + "default_exclusion\n", "test_group\n", - "4a72c253-b3ca-8c13-e615-736a7ebff35cmediumnwb20230802_.nwb\n", + "75286bf3-f876-4550-f235-321f2a7badefmediumnwb20230802_.nwb\n", + "default_exclusion\n", "test_group\n", - "5c53bd33-d57c-fbba-e0fb-55e0bcb85d03mediumnwb20230802_.nwb\n", - "test_group\n", - "614d796c-0b95-6364-aaa0-b6cb1e7bbb83mediumnwb20230802_.nwb\n", - "test_group\n", - "6acb99b8-6a0c-eb83-1141-5f603c5895e0mediumnwb20230802_.nwb\n", - "test_group\n", - "6d039a63-17ad-0b78-4b1e-f02d5f3dbbc5mediumnwb20230802_.nwb\n", - "test_group\n", - "74e10781-1228-4075-0870-af224024ffdcmediumnwb20230802_.nwb\n", - "test_group\n", - "7e3fa66e-727e-1541-819a-b01309bb30aemediumnwb20230802_.nwb\n", - "test_group\n", - "86897349-ff68-ac72-02eb-739dd88936e6mediumnwb20230802_.nwb\n", - "test_group\n", - "8bbddc0f-d6ae-6260-9400-f884a6e25ae8 \n", + "a900c1c8-909d-e583-c377-e98c4f0deebf \n", " \n", - "

    ...

    \n", - "

    Total: 23

    \n", + " \n", + "

    Total: 3

    \n", " " ], "text/plain": [ - "*nwb_file_name *sorted_spikes *spikesorting_\n", - "+------------+ +------------+ +------------+\n", - "mediumnwb20230 test_group 0751a1e1-a406-\n", - "mediumnwb20230 test_group 485a4ddf-332d-\n", - "mediumnwb20230 test_group 4a712103-c223-\n", - "mediumnwb20230 test_group 4a72c253-b3ca-\n", - "mediumnwb20230 test_group 5c53bd33-d57c-\n", - "mediumnwb20230 test_group 614d796c-0b95-\n", - "mediumnwb20230 test_group 6acb99b8-6a0c-\n", - "mediumnwb20230 test_group 6d039a63-17ad-\n", - "mediumnwb20230 test_group 74e10781-1228-\n", - "mediumnwb20230 test_group 7e3fa66e-727e-\n", - "mediumnwb20230 test_group 86897349-ff68-\n", - "mediumnwb20230 test_group 8bbddc0f-d6ae-\n", - " ...\n", - " (Total: 23)" + "*nwb_file_name *unit_filter_p *sorted_spikes *spikesorting_\n", + "+------------+ +------------+ +------------+ +------------+\n", + "mediumnwb20230 default_exclus test_group 143dff79-3779-\n", + "mediumnwb20230 default_exclus test_group 75286bf3-f876-\n", + "mediumnwb20230 default_exclus test_group a900c1c8-909d-\n", + " (Total: 3)" ] }, - "execution_count": 6, + "execution_count": 8, "metadata": {}, "output_type": "execute_result" } ], "source": [ + "# look at the sorting within the group we just made\n", "SortedSpikesGroup.SortGroup & {\n", " \"nwb_file_name\": nwb_copy_file_name,\n", " \"sorted_spikes_group_name\": \"test_group\",\n", + " \"unit_filter_params_name\": unit_filter_params_name,\n", "}" ] }, @@ -652,7 +668,7 @@ }, { "cell_type": "code", - "execution_count": 7, + "execution_count": 9, "metadata": {}, "outputs": [ { @@ -727,18 +743,30 @@ "=BLOB=\n", "=BLOB=contfrag_clusterless_0.5.13\n", "=BLOB=\n", + "=BLOB=contfrag_clusterless_6track\n", + "=BLOB=\n", "=BLOB=contfrag_sorted\n", "=BLOB=\n", "=BLOB=contfrag_sorted_0.5.13\n", "=BLOB=\n", - "=BLOB=nonlocal_clusterless_0.5.13\n", + "=BLOB=j1620210710_contfrag_clusterless_1D\n", + "=BLOB=\n", + "=BLOB=j1620210710_test_contfrag_clusterless\n", + "=BLOB=\n", + "=BLOB=MS2220180629_contfrag_sorted\n", + "=BLOB=\n", + "=BLOB=ms_lineartrack_2023_contfrag_sorted\n", + "=BLOB=\n", + "=BLOB=ms_lineartrack_contfrag_clusterless\n", + "=BLOB=\n", + "=BLOB=ms_lineartrack_contfrag_sorted\n", "=BLOB=\n", - "=BLOB=nonlocal_sorted_0.5.13\n", + "=BLOB=ms_wtrack_2023_contfrag_sorted\n", "=BLOB=\n", "=BLOB= \n", " \n", - " \n", - "

    Total: 6

    \n", + "

    ...

    \n", + "

    Total: 15

    \n", " " ], "text/plain": [ @@ -746,14 +774,21 @@ "+------------+ +--------+ +--------+\n", "contfrag_clust =BLOB= =BLOB= \n", "contfrag_clust =BLOB= =BLOB= \n", + "contfrag_clust =BLOB= =BLOB= \n", "contfrag_sorte =BLOB= =BLOB= \n", "contfrag_sorte =BLOB= =BLOB= \n", - "nonlocal_clust =BLOB= =BLOB= \n", - "nonlocal_sorte =BLOB= =BLOB= \n", - " (Total: 6)" + "j1620210710_co =BLOB= =BLOB= \n", + "j1620210710_te =BLOB= =BLOB= \n", + "MS2220180629_c =BLOB= =BLOB= \n", + "ms_lineartrack =BLOB= =BLOB= \n", + "ms_lineartrack =BLOB= =BLOB= \n", + "ms_lineartrack =BLOB= =BLOB= \n", + "ms_wtrack_2023 =BLOB= =BLOB= \n", + " ...\n", + " (Total: 15)" ] }, - "execution_count": 7, + "execution_count": 9, "metadata": {}, "output_type": "execute_result" } @@ -795,127 +830,13 @@ }, { "cell_type": "code", - "execution_count": 8, - "metadata": {}, - "outputs": [ - { - "data": { - "text/html": [ - "\n", - " \n", - " \n", - " \n", - " \n", - "
    \n", - " \n", - " \n", - " \n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "
    \n", - "

    nwb_file_name

    \n", - " name of the NWB file\n", - "
    \n", - "

    sorted_spikes_group_name

    \n", - " \n", - "
    \n", - "

    position_group_name

    \n", - " \n", - "
    \n", - "

    decoding_param_name

    \n", - " a name for this set of parameters\n", - "
    \n", - "

    encoding_interval

    \n", - " descriptive name of this interval list\n", - "
    \n", - "

    decoding_interval

    \n", - " descriptive name of this interval list\n", - "
    \n", - "

    estimate_decoding_params

    \n", - " whether to estimate the decoding parameters\n", - "
    mediumnwb20230802_.nwbtest_grouptest_groupcontfrag_sortedpos 0 valid timestest decoding interval0
    \n", - " \n", - "

    Total: 1

    \n", - " " - ], - "text/plain": [ - "*nwb_file_name *sorted_spikes *position_grou *decoding_para *encoding_inte *decoding_inte *estimate_deco\n", - "+------------+ +------------+ +------------+ +------------+ +------------+ +------------+ +------------+\n", - "mediumnwb20230 test_group test_group contfrag_sorte pos 0 valid ti test decoding 0 \n", - " (Total: 1)" - ] - }, - "execution_count": 8, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "from spyglass.decoding.v1.sorted_spikes import SortedSpikesDecodingSelection\n", - "\n", - "SortedSpikesDecodingSelection()" - ] - }, - { - "cell_type": "code", - "execution_count": 9, + "execution_count": 2, "metadata": {}, "outputs": [], "source": [ "selection_key = {\n", " \"sorted_spikes_group_name\": \"test_group\",\n", + " \"unit_filter_params_name\": \"default_exclusion\",\n", " \"position_group_name\": \"test_group\",\n", " \"decoding_param_name\": \"contfrag_sorted\",\n", " \"nwb_file_name\": \"mediumnwb20230802_.nwb\",\n", @@ -924,6 +845,7 @@ " \"estimate_decoding_params\": False,\n", "}\n", "\n", + "from spyglass.decoding import SortedSpikesDecodingSelection\n", "SortedSpikesDecodingSelection.insert1(\n", " selection_key,\n", " skip_duplicates=True,\n", @@ -932,48 +854,26 @@ }, { "cell_type": "code", - "execution_count": 10, + "execution_count": 14, "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ - "[2024-01-17 22:49:10,894][WARNING]: Skipped checksum for file with hash: a04cfc1f-8a7d-48a8-4680-ad1ded1805ca, and path: /Users/edeno/Documents/GitHub/spyglass/DATA/analysis/mediumnwb20230802/mediumnwb20230802_JC0NTAX2E2.nwb\n", - "[2024-01-17 22:49:11,244][WARNING]: Skipped checksum for file with hash: 6629fd95-636a-4ad4-c9af-cee507de2130, and path: /Users/edeno/Documents/GitHub/spyglass/DATA/analysis/mediumnwb20230802/mediumnwb20230802_AMBBKQ9RIY.nwb\n", - "[2024-01-17 22:49:11,482][WARNING]: Skipped checksum for file with hash: 6d04cbdb-e1e4-f44f-7274-0e1ab0356d75, and path: /Users/edeno/Documents/GitHub/spyglass/DATA/analysis/mediumnwb20230802/mediumnwb20230802_W1MLF0Q86S.nwb\n", - "[2024-01-17 22:49:11,741][WARNING]: Skipped checksum for file with hash: 8993754e-7dbe-94a1-403d-8c55aa9c6c42, and path: /Users/edeno/Documents/GitHub/spyglass/DATA/analysis/mediumnwb20230802/mediumnwb20230802_JN4A4GSLZB.nwb\n", - "[2024-01-17 22:49:11,986][WARNING]: Skipped checksum for file with hash: 9e24661c-b021-6ad4-f224-89e331334f18, and path: /Users/edeno/Documents/GitHub/spyglass/DATA/analysis/mediumnwb20230802/mediumnwb20230802_T2DBO3EMZ8.nwb\n", - "[2024-01-17 22:49:12,215][WARNING]: Skipped checksum for file with hash: f64f34ee-e72d-e566-a048-65f2ea31708a, and path: /Users/edeno/Documents/GitHub/spyglass/DATA/analysis/mediumnwb20230802/mediumnwb20230802_USMRXAAV8I.nwb\n", - "[2024-01-17 22:49:12,435][WARNING]: Skipped checksum for file with hash: 6d13e338-41bd-b011-beb5-4de53d9d467b, and path: /Users/edeno/Documents/GitHub/spyglass/DATA/analysis/mediumnwb20230802/mediumnwb20230802_JA2OA12RPN.nwb\n", - "[2024-01-17 22:49:12,661][WARNING]: Skipped checksum for file with hash: d740eb7d-ce29-e140-06a2-c56655e0842a, and path: /Users/edeno/Documents/GitHub/spyglass/DATA/analysis/mediumnwb20230802/mediumnwb20230802_L92EE1VRPB.nwb\n", - "[2024-01-17 22:49:12,889][WARNING]: Skipped checksum for file with hash: 1f386cd3-89da-0233-03ff-76ba94e91a3a, and path: /Users/edeno/Documents/GitHub/spyglass/DATA/analysis/mediumnwb20230802/mediumnwb20230802_TX2ZX3DAP4.nwb\n", - "[2024-01-17 22:49:13,105][WARNING]: Skipped checksum for file with hash: fa76d419-77a4-697a-325d-5c2ddbe517f9, and path: /Users/edeno/Documents/GitHub/spyglass/DATA/analysis/mediumnwb20230802/mediumnwb20230802_0R6AWXMC6G.nwb\n", - "[2024-01-17 22:49:13,326][WARNING]: Skipped checksum for file with hash: ce4cb0c3-3dd0-70fd-8ea0-98a8b84592d9, and path: /Users/edeno/Documents/GitHub/spyglass/DATA/analysis/mediumnwb20230802/mediumnwb20230802_7UIA2ILMG6.nwb\n", - "[2024-01-17 22:49:13,542][WARNING]: Skipped checksum for file with hash: e43f95ff-9779-b980-00a3-99e104864462, and path: /Users/edeno/Documents/GitHub/spyglass/DATA/analysis/mediumnwb20230802/mediumnwb20230802_AKOI7OTASI.nwb\n", - "[2024-01-17 22:49:13,768][WARNING]: Skipped checksum for file with hash: ff81d274-17f7-702d-a2b4-92ac43c29316, and path: /Users/edeno/Documents/GitHub/spyglass/DATA/analysis/mediumnwb20230802/mediumnwb20230802_Y2YF504C5D.nwb\n", - "[2024-01-17 22:49:14,033][WARNING]: Skipped checksum for file with hash: e282a8e5-844b-20f6-345c-cded12e761a9, and path: /Users/edeno/Documents/GitHub/spyglass/DATA/analysis/mediumnwb20230802/mediumnwb20230802_DUNM1TZUGR.nwb\n", - "[2024-01-17 22:49:14,248][WARNING]: Skipped checksum for file with hash: 7d05460d-7366-27c9-2ba7-de2ad5d402f2, and path: /Users/edeno/Documents/GitHub/spyglass/DATA/analysis/mediumnwb20230802/mediumnwb20230802_4JXWFJ3JRI.nwb\n", - "[2024-01-17 22:49:14,478][WARNING]: Skipped checksum for file with hash: c202eb9e-ca43-0a72-4086-57a5bb6eb937, and path: /Users/edeno/Documents/GitHub/spyglass/DATA/analysis/mediumnwb20230802/mediumnwb20230802_5TY04H3B5T.nwb\n", - "[2024-01-17 22:49:14,694][WARNING]: Skipped checksum for file with hash: 4357905c-c6b9-3990-4d62-740a54cfc667, and path: /Users/edeno/Documents/GitHub/spyglass/DATA/analysis/mediumnwb20230802/mediumnwb20230802_X84BYVM2B0.nwb\n", - "[2024-01-17 22:49:14,917][WARNING]: Skipped checksum for file with hash: 4c1103ac-eaca-b282-e5ff-aa2194e65a43, and path: /Users/edeno/Documents/GitHub/spyglass/DATA/analysis/mediumnwb20230802/mediumnwb20230802_2R6VQ8EDL4.nwb\n", - "[2024-01-17 22:49:15,142][WARNING]: Skipped checksum for file with hash: 023c874f-8114-3ef6-7fcf-813844787d5f, and path: /Users/edeno/Documents/GitHub/spyglass/DATA/analysis/mediumnwb20230802/mediumnwb20230802_L7HDY9IDHO.nwb\n", - "[2024-01-17 22:49:15,364][WARNING]: Skipped checksum for file with hash: fde8b240-6adc-86f0-6391-f3f6fad72ee9, and path: /Users/edeno/Documents/GitHub/spyglass/DATA/analysis/mediumnwb20230802/mediumnwb20230802_HWU3E4EKP4.nwb\n", - "[2024-01-17 22:49:15,591][WARNING]: Skipped checksum for file with hash: c592e63b-4db1-40be-632e-0180e6fa02d7, and path: /Users/edeno/Documents/GitHub/spyglass/DATA/analysis/mediumnwb20230802/mediumnwb20230802_SGAU9PX7US.nwb\n", - "[2024-01-17 22:49:15,826][WARNING]: Skipped checksum for file with hash: 148d9058-e6dc-e959-4c4d-75db9aa0b6e4, and path: /Users/edeno/Documents/GitHub/spyglass/DATA/analysis/mediumnwb20230802/mediumnwb20230802_EF6N6XI3AH.nwb\n", - "[2024-01-17 22:49:16,050][WARNING]: Skipped checksum for file with hash: b4b6404f-aaf8-c4cc-9abe-ceea56e103f3, and path: /Users/edeno/Documents/GitHub/spyglass/DATA/analysis/mediumnwb20230802/mediumnwb20230802_O7ZZ0F1XN7.nwb\n", - "[2024-01-17 22:49:16,287][WARNING]: Skipped checksum for file with hash: 26f7bdc7-da8d-6ad5-3f4a-554ceb48755e, and path: /Users/edeno/Documents/GitHub/spyglass/DATA/analysis/mediumnwb20230802/mediumnwb20230802_0TKF5589B7.nwb\n" + "[12:19:30][WARNING] Spyglass: Upsampled position data, frame indices are invalid. Setting add_frame_ind=False\n", + "No GPU/TPU found, falling back to CPU. (Set TF_CPP_MIN_LOG_LEVEL=0 and rerun for more info.)\n" ] }, { "data": { "application/vnd.jupyter.widget-view+json": { - "model_id": "810a8c3783d646cda568f23d1853b38f", + "model_id": "90545a744afe4ddfb30e59e070c29cdd", "version_major": 2, "version_minor": 0 }, "text/plain": [ - "Encoding models: 0%| | 0/23 [00:00nwb_file_name

    \n", " name of the NWB file\n", "
    \n", + "

    unit_filter_params_name

    \n", + " \n", + "
    \n", "

    sorted_spikes_group_name

    \n", " \n", "
    \n", @@ -1105,8 +998,9 @@ "

    estimate_decoding_params

    \n", " whether to estimate the decoding parameters\n", "
    \n", - " 650316f6-e19b-6195-5aea-0f46bc503fa3\n", + " 42e9e7f9-a6f2-9242-63ce-94228bc72743\n", "mediumnwb20230802_.nwb\n", + "default_exclusion\n", "test_group\n", "test_group\n", "contfrag_sorted\n", @@ -1119,13 +1013,13 @@ " " ], "text/plain": [ - "*merge_id nwb_file_name sorted_spikes_ position_group decoding_param encoding_inter decoding_inter estimate_decod\n", - "+------------+ +------------+ +------------+ +------------+ +------------+ +------------+ +------------+ +------------+\n", - "650316f6-e19b- mediumnwb20230 test_group test_group contfrag_sorte pos 0 valid ti test decoding 0 \n", + "*merge_id nwb_file_name unit_filter_pa sorted_spikes_ position_group decoding_param encoding_inter decoding_inter estimate_decod\n", + "+------------+ +------------+ +------------+ +------------+ +------------+ +------------+ +------------+ +------------+ +------------+\n", + "42e9e7f9-a6f2- mediumnwb20230 default_exclus test_group test_group contfrag_sorte pos 0 valid ti test decoding 0 \n", " (Total: 1)" ] }, - "execution_count": 11, + "execution_count": 3, "metadata": {}, "output_type": "execute_result" } @@ -1145,20 +1039,9 @@ }, { "cell_type": "code", - "execution_count": 12, + "execution_count": 6, "metadata": {}, "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "[2024-01-17 22:50:37,762][WARNING]: Skipped checksum for file with hash: 929bf936-5d90-ef32-a736-fb41f4d4932c, and path: /Users/edeno/Documents/GitHub/spyglass/DATA/analysis/mediumnwb20230802/mediumnwb20230802_39518860-b21c-47e4-8a4f-cf7e040e313f.nc\n", - "/Users/edeno/miniconda3/envs/spyglass/lib/python3.9/site-packages/xarray/namedarray/core.py:487: UserWarning: Duplicate dimension names present: dimensions {'states'} appear more than once in dims=('states', 'states'). We do not yet support duplicate dimension names, but we do allow initial construction of the object. We recommend you rename the dims immediately to become distinct, as most xarray functionality is likely to fail silently if you do not. To rename the dimensions you will need to set the ``.dims`` attribute of each variable, ``e.g. var.dims=('x0', 'x1')``.\n", - " warnings.warn(\n", - "/Users/edeno/miniconda3/envs/spyglass/lib/python3.9/site-packages/xarray/namedarray/core.py:487: UserWarning: Duplicate dimension names present: dimensions {'states'} appear more than once in dims=('states', 'states'). We do not yet support duplicate dimension names, but we do allow initial construction of the object. We recommend you rename the dims immediately to become distinct, as most xarray functionality is likely to fail silently if you do not. To rename the dimensions you will need to set the ``.dims`` attribute of each variable, ``e.g. var.dims=('x0', 'x1')``.\n", - " warnings.warn(\n" - ] - }, { "data": { "text/html": [ @@ -1526,8 +1409,8 @@ " fill: currentColor;\n", "}\n", "
    <xarray.Dataset>\n",
    -       "Dimensions:                      (state_ind: 26668, dim_0: 26668, time: 451,\n",
    -       "                                  states: 2, intervals: 1, state_bins: 26668)\n",
    +       "Dimensions:                      (state_ind: 25752, dim_0: 25752, time: 5001,\n",
    +       "                                  states: 2, intervals: 1, state_bins: 25752)\n",
            "Coordinates:\n",
            "  * state_ind                    (state_ind) int32 0 0 0 0 0 0 0 ... 1 1 1 1 1 1\n",
            "  * time                         (time) float64 1.626e+09 ... 1.626e+09\n",
    @@ -1536,8 +1419,8 @@
            "    encoding_groups              (states) int32 ...\n",
            "  * state_bins                   (state_bins) object MultiIndex\n",
            "  * state                        (state_bins) object 'Continuous' ... 'Fragme...\n",
    -       "  * x_position                   (state_bins) float64 29.02 29.02 ... 262.7\n",
    -       "  * y_position                   (state_bins) float64 0.4493 2.445 ... 224.0\n",
    +       "  * x_position                   (state_bins) float64 29.02 29.02 ... 258.8\n",
    +       "  * y_position                   (state_bins) float64 5.828 7.811 ... 224.0\n",
            "Dimensions without coordinates: dim_0, intervals\n",
            "Data variables:\n",
            "    initial_conditions           (dim_0) float64 ...\n",
    @@ -1545,54 +1428,54 @@
            "    acausal_posterior            (intervals, time, state_bins) float32 ...\n",
            "    acausal_state_probabilities  (intervals, time, states) float64 ...\n",
            "Attributes:\n",
    -       "    marginal_log_likelihoods:  -16366.834
  • marginal_log_likelihoods :
    -39514.59
  • " ], "text/plain": [ "\n", - "Dimensions: (state_ind: 26668, dim_0: 26668, time: 451,\n", - " states: 2, intervals: 1, state_bins: 26668)\n", + "Dimensions: (state_ind: 25752, dim_0: 25752, time: 5001,\n", + " states: 2, intervals: 1, state_bins: 25752)\n", "Coordinates:\n", " * state_ind (state_ind) int32 0 0 0 0 0 0 0 ... 1 1 1 1 1 1\n", " * time (time) float64 1.626e+09 ... 1.626e+09\n", @@ -1601,8 +1484,8 @@ " encoding_groups (states) int32 ...\n", " * state_bins (state_bins) object MultiIndex\n", " * state (state_bins) object 'Continuous' ... 'Fragme...\n", - " * x_position (state_bins) float64 29.02 29.02 ... 262.7\n", - " * y_position (state_bins) float64 0.4493 2.445 ... 224.0\n", + " * x_position (state_bins) float64 29.02 29.02 ... 258.8\n", + " * y_position (state_bins) float64 5.828 7.811 ... 224.0\n", "Dimensions without coordinates: dim_0, intervals\n", "Data variables:\n", " initial_conditions (dim_0) float64 ...\n", @@ -1610,16 +1493,17 @@ " acausal_posterior (intervals, time, state_bins) float32 ...\n", " acausal_state_probabilities (intervals, time, states) float64 ...\n", "Attributes:\n", - " marginal_log_likelihoods: -16366.834" + " marginal_log_likelihoods: -39514.59" ] }, - "execution_count": 12, + "execution_count": 6, "metadata": {}, "output_type": "execute_result" } ], "source": [ - "results = (SortedSpikesDecodingV1 & selection_key).load_results()\n", + "\n", + "results = (SortedSpikesDecodingV1 & selection_key).fetch_results()\n", "results" ] }, diff --git a/notebooks/51_MUA_Detection.ipynb b/notebooks/51_MUA_Detection.ipynb new file mode 100644 index 000000000..e8e51f66d --- /dev/null +++ b/notebooks/51_MUA_Detection.ipynb @@ -0,0 +1,2808 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "from pathlib import Path\n", + "import datajoint as dj\n", + "\n", + "dj.config.load(\n", + " Path(\"../dj_local_conf.json\").absolute()\n", + ") # load config for database connection info" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# MUA Analysis and Detection\n", + "\n", + "NOTE: This notebook is a work in progress. It is not yet complete and may contain errors." + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[2024-01-29 13:51:25,319][INFO]: Connecting root@localhost:3306\n", + "[2024-01-29 13:51:25,405][INFO]: Connected root@localhost:3306\n", + "[13:51:26][WARNING] Spyglass: Please update position_tools to >= 0.1.0\n" + ] + }, + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + "
    \n", + " \n", + " \n", + " \n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "
    \n", + "

    sorting_id

    \n", + " \n", + "
    \n", + "

    merge_id

    \n", + " \n", + "
    \n", + "

    recording_id

    \n", + " \n", + "
    \n", + "

    sorter

    \n", + " \n", + "
    \n", + "

    sorter_param_name

    \n", + " \n", + "
    \n", + "

    nwb_file_name

    \n", + " name of the NWB file\n", + "
    \n", + "

    interval_list_name

    \n", + " descriptive name of this interval list\n", + "
    \n", + "

    curation_id

    \n", + " \n", + "
    08a302b6-5505-40fa-b4d5-62162f8eef58485a4ddf-332d-35b5-3ad4-0561736c1844449b64e3-db0b-437e-a1b9-0d29928aa2ddclusterless_thresholderdefault_clusterlessmediumnwb20230802_.nwb45f6b9a1-eef3-46eb-866d-d0999afebda60
    0ca508ee-af4c-4a89-8181-d48bd209bfd46acb99b8-6a0c-eb83-1141-5f603c5895e0328da21c-1d9c-41e2-9800-76b3484b707bclusterless_thresholderdefault_clusterlessmediumnwb20230802_.nwb686d9951-1c0f-4d5e-9f5c-09e6fd8bdd4c0
    209dc048-6fae-4315-b293-c06fff29f947f7237e18-4e73-4aee-805b-90735e9147deaff78f2f-2ba0-412a-95cc-447c3a2f4683clusterless_thresholderdefault_clusterlessmediumnwb20230802_.nwb719e8a86-fcf1-4ffc-8c1f-ea912f67ad5d0
    21a9a593-f6f3-4b82-99d7-8fc46556eff37e3fa66e-727e-1541-819a-b01309bb30ae2402805a-04f9-4a88-9ccf-071376c8de19clusterless_thresholderdefault_clusterlessmediumnwb20230802_.nwbd581b117-160e-4311-b096-7781a4de43940
    406a20e3-5a9f-4fec-b046-a6561f72461e6d039a63-17ad-0b78-4b1e-f02d5f3dbbc5f1427e00-2974-4301-b2ac-b4dc29277c51clusterless_thresholderdefault_clusterlessmediumnwb20230802_.nwb0e848c38-9105-4ea4-b6ba-dbdd5b46a0880
    4131c51b-c56d-41fa-b046-46635fc17fd9e0e9133a-7a4e-1321-a43a-e8afcb2f25da9e332d82-1daf-4e92-bb50-12e4f9430875clusterless_thresholderdefault_clusterlessmediumnwb20230802_.nwb9ed11db5-c42e-491a-8caf-7d9a37a65f130
    4c5a629a-71d9-481d-ab11-a4cb0fc160879959b614-2318-f597-6651-a3a82124d28a3a2c3eed-413a-452a-83c8-0e4648141bdeclusterless_thresholderdefault_clusterlessmediumnwb20230802_.nwb2b9fbf14-74a0-4294-a805-26702340aac90
    4d629c07-1931-4e1f-a3a8-cbf1b72161e3c0eb6455-fc41-c200-b62e-e3ca81b9a3f7f07bc0b0-de6b-4424-8ef9-766213aaca26clusterless_thresholderdefault_clusterlessmediumnwb20230802_.nwb5c68f0f0-f577-4905-8a09-e4d171d0a22d0
    554a9a3c-0461-48be-8435-123eed59c228912e250e-56d8-ee33-4525-c844d810971b7f128981-6868-4976-ba20-248655dcac21clusterless_thresholderdefault_clusterlessmediumnwb20230802_.nwbf4b9301f-bc91-455b-9474-c801093f38560
    7bb007f2-26d3-463f-b7dc-7bd4d271725ed7d2c97a-0e6e-d1b8-735c-d55dc66a30e1a9b7cec0-1256-49cf-abf0-8c45fd155379clusterless_thresholderdefault_clusterlessmediumnwb20230802_.nwb74270cba-36ee-4afb-ab50-2a6cc948e68c0
    80e1f37f-48a7-4087-bd37-7a37b6a2c160abb92dce-4410-8f17-a501-a4104bda0dcf3c40ebdc-0b61-4105-9971-e1348bd49bc7clusterless_thresholderdefault_clusterlessmediumnwb20230802_.nwb0f91197e-bebb-4dc6-ad41-5bf89c3eed280
    8848c4a8-a2f2-4f3d-82cd-51b13b8bae3c74e10781-1228-4075-0870-af224024ffdc257c077b-8f3b-4abb-a631-6b8084d6a1eaclusterless_thresholderdefault_clusterlessmediumnwb20230802_.nwbe289e03d-32ad-461a-a1cc-c885373431490
    \n", + "

    ...

    \n", + "

    Total: 23

    \n", + " " + ], + "text/plain": [ + "*sorting_id *merge_id recording_id sorter sorter_param_n nwb_file_name interval_list_ curation_id \n", + "+------------+ +------------+ +------------+ +------------+ +------------+ +------------+ +------------+ +------------+\n", + "08a302b6-5505- 485a4ddf-332d- 449b64e3-db0b- clusterless_th default_cluste mediumnwb20230 45f6b9a1-eef3- 0 \n", + "0ca508ee-af4c- 6acb99b8-6a0c- 328da21c-1d9c- clusterless_th default_cluste mediumnwb20230 686d9951-1c0f- 0 \n", + "209dc048-6fae- f7237e18-4e73- aff78f2f-2ba0- clusterless_th default_cluste mediumnwb20230 719e8a86-fcf1- 0 \n", + "21a9a593-f6f3- 7e3fa66e-727e- 2402805a-04f9- clusterless_th default_cluste mediumnwb20230 d581b117-160e- 0 \n", + "406a20e3-5a9f- 6d039a63-17ad- f1427e00-2974- clusterless_th default_cluste mediumnwb20230 0e848c38-9105- 0 \n", + "4131c51b-c56d- e0e9133a-7a4e- 9e332d82-1daf- clusterless_th default_cluste mediumnwb20230 9ed11db5-c42e- 0 \n", + "4c5a629a-71d9- 9959b614-2318- 3a2c3eed-413a- clusterless_th default_cluste mediumnwb20230 2b9fbf14-74a0- 0 \n", + "4d629c07-1931- c0eb6455-fc41- f07bc0b0-de6b- clusterless_th default_cluste mediumnwb20230 5c68f0f0-f577- 0 \n", + "554a9a3c-0461- 912e250e-56d8- 7f128981-6868- clusterless_th default_cluste mediumnwb20230 f4b9301f-bc91- 0 \n", + "7bb007f2-26d3- d7d2c97a-0e6e- a9b7cec0-1256- clusterless_th default_cluste mediumnwb20230 74270cba-36ee- 0 \n", + "80e1f37f-48a7- abb92dce-4410- 3c40ebdc-0b61- clusterless_th default_cluste mediumnwb20230 0f91197e-bebb- 0 \n", + "8848c4a8-a2f2- 74e10781-1228- 257c077b-8f3b- clusterless_th default_cluste mediumnwb20230 e289e03d-32ad- 0 \n", + " ...\n", + " (Total: 23)" + ] + }, + "execution_count": 2, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "from spyglass.spikesorting.spikesorting_merge import SpikeSortingOutput\n", + "import spyglass.spikesorting.v1 as sgs\n", + "\n", + "\n", + "nwb_copy_file_name = \"mediumnwb20230802_.nwb\"\n", + "\n", + "sorter_keys = {\n", + " \"nwb_file_name\": nwb_copy_file_name,\n", + " \"sorter\": \"clusterless_thresholder\",\n", + " \"sorter_param_name\": \"default_clusterless\",\n", + "}\n", + "\n", + "(sgs.SpikeSortingSelection & sorter_keys) * SpikeSortingOutput.CurationV1" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "array([UUID('485a4ddf-332d-35b5-3ad4-0561736c1844'),\n", + " UUID('6acb99b8-6a0c-eb83-1141-5f603c5895e0'),\n", + " UUID('f7237e18-4e73-4aee-805b-90735e9147de'),\n", + " UUID('7e3fa66e-727e-1541-819a-b01309bb30ae'),\n", + " UUID('6d039a63-17ad-0b78-4b1e-f02d5f3dbbc5'),\n", + " UUID('e0e9133a-7a4e-1321-a43a-e8afcb2f25da'),\n", + " UUID('9959b614-2318-f597-6651-a3a82124d28a'),\n", + " UUID('c0eb6455-fc41-c200-b62e-e3ca81b9a3f7'),\n", + " UUID('912e250e-56d8-ee33-4525-c844d810971b'),\n", + " UUID('d7d2c97a-0e6e-d1b8-735c-d55dc66a30e1'),\n", + " UUID('abb92dce-4410-8f17-a501-a4104bda0dcf'),\n", + " UUID('74e10781-1228-4075-0870-af224024ffdc'),\n", + " UUID('8bbddc0f-d6ae-6260-9400-f884a6e25ae8'),\n", + " UUID('614d796c-0b95-6364-aaa0-b6cb1e7bbb83'),\n", + " UUID('b332482b-e430-169d-8ac0-0a73ce968ed7'),\n", + " UUID('86897349-ff68-ac72-02eb-739dd88936e6'),\n", + " UUID('4a712103-c223-864f-82e0-6c23de79cc14'),\n", + " UUID('cf858380-e8a3-49de-c2a9-1a277e307a68'),\n", + " UUID('cc4ee561-f974-f8e5-0ea4-83185263ac67'),\n", + " UUID('4a72c253-b3ca-8c13-e615-736a7ebff35c'),\n", + " UUID('b92a94d8-ee1e-2097-a81f-5c1e1556ed24'),\n", + " UUID('5c53bd33-d57c-fbba-e0fb-55e0bcb85d03'),\n", + " UUID('0751a1e1-a406-7f87-ae6f-ce4ffc60621c')], dtype=object)" + ] + }, + "execution_count": 3, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "spikesorting_merge_ids = (\n", + " (sgs.SpikeSortingSelection & sorter_keys) * SpikeSortingOutput.CurationV1\n", + ").fetch(\"merge_id\")\n", + "\n", + "spikesorting_merge_ids" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + "
    \n", + " \n", + " \n", + " \n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "
    \n", + "

    merge_id

    \n", + " \n", + "
    \n", + "

    spikesorting_merge_id

    \n", + " \n", + "
    \n", + "

    unit_group_name

    \n", + " Name of unit group\n", + "
    39b22078-84fa-d3aa-8ca9-2368603d6a470751a1e1-a406-7f87-ae6f-ce4ffc60621call units
    7bc69ef8-ae89-f30f-c236-56a87a49ed63485a4ddf-332d-35b5-3ad4-0561736c1844all units
    2f6295c6-ad14-dde0-6b14-ee29bc2ed8494a712103-c223-864f-82e0-6c23de79cc14all units
    7fa3c0ad-36a8-c14c-d84a-890c6002a4574a72c253-b3ca-8c13-e615-736a7ebff35call units
    4b025478-ab06-8e65-ef09-7e32be5a624c5c53bd33-d57c-fbba-e0fb-55e0bcb85d03all units
    9658d944-1f1f-d467-1f56-bcc32d63e6e8614d796c-0b95-6364-aaa0-b6cb1e7bbb83all units
    76cb7574-a687-37c9-1045-8e4e5d13a0b06acb99b8-6a0c-eb83-1141-5f603c5895e0all units
    87af74fa-a77e-f29b-99f7-f5720aa4816f6d039a63-17ad-0b78-4b1e-f02d5f3dbbc5all units
    3cccfce5-dad9-61c5-7eee-1c708183710074e10781-1228-4075-0870-af224024ffdcall units
    bbddf25f-d810-f586-e3b8-cb96350fbbde7e3fa66e-727e-1541-819a-b01309bb30aeall units
    7887e5db-da1d-d261-d58a-a5175759396586897349-ff68-ac72-02eb-739dd88936e6all units
    1b7ba376-89f9-e0ac-9104-fbd1bd984e418bbddc0f-d6ae-6260-9400-f884a6e25ae8all units
    \n", + "

    ...

    \n", + "

    Total: 23

    \n", + " " + ], + "text/plain": [ + "*merge_id spikesorting_m unit_group_nam\n", + "+------------+ +------------+ +------------+\n", + "39b22078-84fa- 0751a1e1-a406- all units \n", + "7bc69ef8-ae89- 485a4ddf-332d- all units \n", + "2f6295c6-ad14- 4a712103-c223- all units \n", + "7fa3c0ad-36a8- 4a72c253-b3ca- all units \n", + "4b025478-ab06- 5c53bd33-d57c- all units \n", + "9658d944-1f1f- 614d796c-0b95- all units \n", + "76cb7574-a687- 6acb99b8-6a0c- all units \n", + "87af74fa-a77e- 6d039a63-17ad- all units \n", + "3cccfce5-dad9- 74e10781-1228- all units \n", + "bbddf25f-d810- 7e3fa66e-727e- all units \n", + "7887e5db-da1d- 86897349-ff68- all units \n", + "1b7ba376-89f9- 8bbddc0f-d6ae- all units \n", + " ...\n", + " (Total: 23)" + ] + }, + "execution_count": 4, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "from spyglass.spikesorting.unit_inclusion_merge import (\n", + " ImportedUnitInclusionV1,\n", + " UnitInclusionOutput,\n", + ")\n", + "\n", + "ImportedUnitInclusionV1().insert_all_units(spikesorting_merge_ids)\n", + "\n", + "UnitInclusionOutput.ImportedUnitInclusionV1() & [\n", + " {\"spikesorting_merge_id\": id} for id in spikesorting_merge_ids\n", + "]" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + "
    \n", + " \n", + " \n", + " \n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "
    \n", + "

    merge_id

    \n", + " \n", + "
    \n", + "

    spikesorting_merge_id

    \n", + " \n", + "
    \n", + "

    unit_group_name

    \n", + " Name of unit group\n", + "
    39b22078-84fa-d3aa-8ca9-2368603d6a470751a1e1-a406-7f87-ae6f-ce4ffc60621call units
    7bc69ef8-ae89-f30f-c236-56a87a49ed63485a4ddf-332d-35b5-3ad4-0561736c1844all units
    2f6295c6-ad14-dde0-6b14-ee29bc2ed8494a712103-c223-864f-82e0-6c23de79cc14all units
    7fa3c0ad-36a8-c14c-d84a-890c6002a4574a72c253-b3ca-8c13-e615-736a7ebff35call units
    4b025478-ab06-8e65-ef09-7e32be5a624c5c53bd33-d57c-fbba-e0fb-55e0bcb85d03all units
    9658d944-1f1f-d467-1f56-bcc32d63e6e8614d796c-0b95-6364-aaa0-b6cb1e7bbb83all units
    76cb7574-a687-37c9-1045-8e4e5d13a0b06acb99b8-6a0c-eb83-1141-5f603c5895e0all units
    87af74fa-a77e-f29b-99f7-f5720aa4816f6d039a63-17ad-0b78-4b1e-f02d5f3dbbc5all units
    3cccfce5-dad9-61c5-7eee-1c708183710074e10781-1228-4075-0870-af224024ffdcall units
    bbddf25f-d810-f586-e3b8-cb96350fbbde7e3fa66e-727e-1541-819a-b01309bb30aeall units
    7887e5db-da1d-d261-d58a-a5175759396586897349-ff68-ac72-02eb-739dd88936e6all units
    1b7ba376-89f9-e0ac-9104-fbd1bd984e418bbddc0f-d6ae-6260-9400-f884a6e25ae8all units
    \n", + "

    ...

    \n", + "

    Total: 23

    \n", + " " + ], + "text/plain": [ + "*merge_id spikesorting_m unit_group_nam\n", + "+------------+ +------------+ +------------+\n", + "39b22078-84fa- 0751a1e1-a406- all units \n", + "7bc69ef8-ae89- 485a4ddf-332d- all units \n", + "2f6295c6-ad14- 4a712103-c223- all units \n", + "7fa3c0ad-36a8- 4a72c253-b3ca- all units \n", + "4b025478-ab06- 5c53bd33-d57c- all units \n", + "9658d944-1f1f- 614d796c-0b95- all units \n", + "76cb7574-a687- 6acb99b8-6a0c- all units \n", + "87af74fa-a77e- 6d039a63-17ad- all units \n", + "3cccfce5-dad9- 74e10781-1228- all units \n", + "bbddf25f-d810- 7e3fa66e-727e- all units \n", + "7887e5db-da1d- 86897349-ff68- all units \n", + "1b7ba376-89f9- 8bbddc0f-d6ae- all units \n", + " ...\n", + " (Total: 23)" + ] + }, + "execution_count": 5, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "from spyglass.spikesorting.unit_inclusion_merge import (\n", + " ImportedUnitInclusionV1,\n", + " UnitInclusionOutput,\n", + ")\n", + "\n", + "ImportedUnitInclusionV1().insert_all_units(spikesorting_merge_ids)\n", + "\n", + "UnitInclusionOutput.ImportedUnitInclusionV1() & [\n", + " {\"spikesorting_merge_id\": id} for id in spikesorting_merge_ids\n", + "]" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + "
    \n", + " \n", + " \n", + " \n", + "\n", + "
    \n", + "

    nwb_file_name

    \n", + " name of the NWB file\n", + "
    \n", + "

    sorted_spikes_group_name

    \n", + " \n", + "
    mediumnwb20230802_.nwbtest_group
    \n", + " \n", + "

    Total: 1

    \n", + " " + ], + "text/plain": [ + "*nwb_file_name *sorted_spikes\n", + "+------------+ +------------+\n", + "mediumnwb20230 test_group \n", + " (Total: 1)" + ] + }, + "execution_count": 6, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "from spyglass.spikesorting.unit_inclusion_merge import SortedSpikesGroup\n", + "\n", + "unit_inclusion_merge_ids = (\n", + " UnitInclusionOutput.ImportedUnitInclusionV1\n", + " & [{\"spikesorting_merge_id\": id} for id in spikesorting_merge_ids]\n", + ").fetch(\"merge_id\")\n", + "\n", + "SortedSpikesGroup().create_group(\n", + " group_name=\"test_group\",\n", + " nwb_file_name=nwb_copy_file_name,\n", + " unit_inclusion_merge_ids=unit_inclusion_merge_ids,\n", + ")\n", + "\n", + "group_key = {\n", + " \"nwb_file_name\": nwb_copy_file_name,\n", + " \"sorted_spikes_group_name\": \"test_group\",\n", + "}\n", + "\n", + "SortedSpikesGroup & group_key" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + "
    \n", + " \n", + " \n", + " \n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "
    \n", + "

    nwb_file_name

    \n", + " name of the NWB file\n", + "
    \n", + "

    sorted_spikes_group_name

    \n", + " \n", + "
    \n", + "

    unit_inclusion_merge_id

    \n", + " \n", + "
    mediumnwb20230802_.nwbtest_group0363fb94-c5de-d653-ed33-1807fa523790
    mediumnwb20230802_.nwbtest_group12da7476-bb70-a4ee-0558-99ca5bcc0958
    mediumnwb20230802_.nwbtest_group151976b9-9dc6-74f6-65d3-23ce96d006d1
    mediumnwb20230802_.nwbtest_group1b7ba376-89f9-e0ac-9104-fbd1bd984e41
    mediumnwb20230802_.nwbtest_group2f6295c6-ad14-dde0-6b14-ee29bc2ed849
    mediumnwb20230802_.nwbtest_group357a0267-874e-04f0-410e-9711f29e1236
    mediumnwb20230802_.nwbtest_group39b22078-84fa-d3aa-8ca9-2368603d6a47
    mediumnwb20230802_.nwbtest_group3cccfce5-dad9-61c5-7eee-1c7081837100
    mediumnwb20230802_.nwbtest_group4b025478-ab06-8e65-ef09-7e32be5a624c
    mediumnwb20230802_.nwbtest_group7591b69d-a902-9058-7597-04632de9e08c
    mediumnwb20230802_.nwbtest_group76cb7574-a687-37c9-1045-8e4e5d13a0b0
    mediumnwb20230802_.nwbtest_group7887e5db-da1d-d261-d58a-a51757593965
    \n", + "

    ...

    \n", + "

    Total: 23

    \n", + " " + ], + "text/plain": [ + "*nwb_file_name *sorted_spikes *unit_inclusio\n", + "+------------+ +------------+ +------------+\n", + "mediumnwb20230 test_group 0363fb94-c5de-\n", + "mediumnwb20230 test_group 12da7476-bb70-\n", + "mediumnwb20230 test_group 151976b9-9dc6-\n", + "mediumnwb20230 test_group 1b7ba376-89f9-\n", + "mediumnwb20230 test_group 2f6295c6-ad14-\n", + "mediumnwb20230 test_group 357a0267-874e-\n", + "mediumnwb20230 test_group 39b22078-84fa-\n", + "mediumnwb20230 test_group 3cccfce5-dad9-\n", + "mediumnwb20230 test_group 4b025478-ab06-\n", + "mediumnwb20230 test_group 7591b69d-a902-\n", + "mediumnwb20230 test_group 76cb7574-a687-\n", + "mediumnwb20230 test_group 7887e5db-da1d-\n", + " ...\n", + " (Total: 23)" + ] + }, + "execution_count": 7, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "SortedSpikesGroup.Units() & group_key" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "An example of how to get spike times" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[2024-01-29 13:51:31,631][WARNING]: Skipped checksum for file with hash: 148d9058-e6dc-e959-4c4d-75db9aa0b6e4, and path: /Users/edeno/Documents/GitHub/spyglass/DATA/analysis/mediumnwb20230802/mediumnwb20230802_EF6N6XI3AH.nwb\n", + "[2024-01-29 13:51:32,089][WARNING]: Skipped checksum for file with hash: b4b6404f-aaf8-c4cc-9abe-ceea56e103f3, and path: /Users/edeno/Documents/GitHub/spyglass/DATA/analysis/mediumnwb20230802/mediumnwb20230802_O7ZZ0F1XN7.nwb\n", + "[2024-01-29 13:51:32,499][WARNING]: Skipped checksum for file with hash: 4357905c-c6b9-3990-4d62-740a54cfc667, and path: /Users/edeno/Documents/GitHub/spyglass/DATA/analysis/mediumnwb20230802/mediumnwb20230802_X84BYVM2B0.nwb\n", + "[2024-01-29 13:51:32,924][WARNING]: Skipped checksum for file with hash: ff81d274-17f7-702d-a2b4-92ac43c29316, and path: /Users/edeno/Documents/GitHub/spyglass/DATA/analysis/mediumnwb20230802/mediumnwb20230802_Y2YF504C5D.nwb\n", + "[2024-01-29 13:51:33,306][WARNING]: Skipped checksum for file with hash: 8993754e-7dbe-94a1-403d-8c55aa9c6c42, and path: /Users/edeno/Documents/GitHub/spyglass/DATA/analysis/mediumnwb20230802/mediumnwb20230802_JN4A4GSLZB.nwb\n", + "[2024-01-29 13:51:33,741][WARNING]: Skipped checksum for file with hash: 7d05460d-7366-27c9-2ba7-de2ad5d402f2, and path: /Users/edeno/Documents/GitHub/spyglass/DATA/analysis/mediumnwb20230802/mediumnwb20230802_4JXWFJ3JRI.nwb\n", + "[2024-01-29 13:51:34,202][WARNING]: Skipped checksum for file with hash: 6629fd95-636a-4ad4-c9af-cee507de2130, and path: /Users/edeno/Documents/GitHub/spyglass/DATA/analysis/mediumnwb20230802/mediumnwb20230802_AMBBKQ9RIY.nwb\n", + "[2024-01-29 13:51:34,735][WARNING]: Skipped checksum for file with hash: fa76d419-77a4-697a-325d-5c2ddbe517f9, and path: /Users/edeno/Documents/GitHub/spyglass/DATA/analysis/mediumnwb20230802/mediumnwb20230802_0R6AWXMC6G.nwb\n", + "[2024-01-29 13:51:35,159][WARNING]: Skipped checksum for file with hash: f64f34ee-e72d-e566-a048-65f2ea31708a, and path: /Users/edeno/Documents/GitHub/spyglass/DATA/analysis/mediumnwb20230802/mediumnwb20230802_USMRXAAV8I.nwb\n", + "[2024-01-29 13:51:35,536][WARNING]: Skipped checksum for file with hash: e282a8e5-844b-20f6-345c-cded12e761a9, and path: /Users/edeno/Documents/GitHub/spyglass/DATA/analysis/mediumnwb20230802/mediumnwb20230802_DUNM1TZUGR.nwb\n", + "[2024-01-29 13:51:35,889][WARNING]: Skipped checksum for file with hash: d740eb7d-ce29-e140-06a2-c56655e0842a, and path: /Users/edeno/Documents/GitHub/spyglass/DATA/analysis/mediumnwb20230802/mediumnwb20230802_L92EE1VRPB.nwb\n", + "[2024-01-29 13:51:36,277][WARNING]: Skipped checksum for file with hash: e43f95ff-9779-b980-00a3-99e104864462, and path: /Users/edeno/Documents/GitHub/spyglass/DATA/analysis/mediumnwb20230802/mediumnwb20230802_AKOI7OTASI.nwb\n", + "[2024-01-29 13:51:36,679][WARNING]: Skipped checksum for file with hash: 6d04cbdb-e1e4-f44f-7274-0e1ab0356d75, and path: /Users/edeno/Documents/GitHub/spyglass/DATA/analysis/mediumnwb20230802/mediumnwb20230802_W1MLF0Q86S.nwb\n", + "[2024-01-29 13:51:37,056][WARNING]: Skipped checksum for file with hash: 9e24661c-b021-6ad4-f224-89e331334f18, and path: /Users/edeno/Documents/GitHub/spyglass/DATA/analysis/mediumnwb20230802/mediumnwb20230802_T2DBO3EMZ8.nwb\n", + "[2024-01-29 13:51:37,738][WARNING]: Skipped checksum for file with hash: 1f386cd3-89da-0233-03ff-76ba94e91a3a, and path: /Users/edeno/Documents/GitHub/spyglass/DATA/analysis/mediumnwb20230802/mediumnwb20230802_TX2ZX3DAP4.nwb\n", + "[2024-01-29 13:51:38,180][WARNING]: Skipped checksum for file with hash: fde8b240-6adc-86f0-6391-f3f6fad72ee9, and path: /Users/edeno/Documents/GitHub/spyglass/DATA/analysis/mediumnwb20230802/mediumnwb20230802_HWU3E4EKP4.nwb\n", + "[2024-01-29 13:51:38,798][WARNING]: Skipped checksum for file with hash: 6d13e338-41bd-b011-beb5-4de53d9d467b, and path: /Users/edeno/Documents/GitHub/spyglass/DATA/analysis/mediumnwb20230802/mediumnwb20230802_JA2OA12RPN.nwb\n", + "[2024-01-29 13:51:39,249][WARNING]: Skipped checksum for file with hash: c202eb9e-ca43-0a72-4086-57a5bb6eb937, and path: /Users/edeno/Documents/GitHub/spyglass/DATA/analysis/mediumnwb20230802/mediumnwb20230802_5TY04H3B5T.nwb\n", + "[2024-01-29 13:51:39,931][WARNING]: Skipped checksum for file with hash: 26f7bdc7-da8d-6ad5-3f4a-554ceb48755e, and path: /Users/edeno/Documents/GitHub/spyglass/DATA/analysis/mediumnwb20230802/mediumnwb20230802_0TKF5589B7.nwb\n", + "[2024-01-29 13:51:40,547][WARNING]: Skipped checksum for file with hash: 023c874f-8114-3ef6-7fcf-813844787d5f, and path: /Users/edeno/Documents/GitHub/spyglass/DATA/analysis/mediumnwb20230802/mediumnwb20230802_L7HDY9IDHO.nwb\n", + "[2024-01-29 13:51:40,963][WARNING]: Skipped checksum for file with hash: ce4cb0c3-3dd0-70fd-8ea0-98a8b84592d9, and path: /Users/edeno/Documents/GitHub/spyglass/DATA/analysis/mediumnwb20230802/mediumnwb20230802_7UIA2ILMG6.nwb\n", + "[2024-01-29 13:51:41,407][WARNING]: Skipped checksum for file with hash: c592e63b-4db1-40be-632e-0180e6fa02d7, and path: /Users/edeno/Documents/GitHub/spyglass/DATA/analysis/mediumnwb20230802/mediumnwb20230802_SGAU9PX7US.nwb\n", + "[2024-01-29 13:51:41,819][WARNING]: Skipped checksum for file with hash: 4c1103ac-eaca-b282-e5ff-aa2194e65a43, and path: /Users/edeno/Documents/GitHub/spyglass/DATA/analysis/mediumnwb20230802/mediumnwb20230802_2R6VQ8EDL4.nwb\n" + ] + }, + { + "data": { + "text/plain": [ + "array([1.62593570e+09, 1.62593570e+09, 1.62593570e+09, ...,\n", + " 1.62593718e+09, 1.62593718e+09, 1.62593718e+09])" + ] + }, + "execution_count": 8, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "spike_times = SortedSpikesGroup.fetch_spike_data(group_key)\n", + "spike_times[0]" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[13:51:42][WARNING] Spyglass: Upsampled position data, frame indices are invalid. Setting add_frame_ind=False\n", + "[2024-01-29 13:51:42,217][WARNING]: Skipped checksum for file with hash: 0cd40383-03e0-44ec-5dac-36c66063796a, and path: /Users/edeno/Documents/GitHub/spyglass/DATA/analysis/mediumnwb20230802/mediumnwb20230802_FUSH604NQA.nwb\n" + ] + }, + { + "data": { + "text/html": [ + "
    \n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
    position_xposition_yorientationvelocity_xvelocity_yspeed
    time
    1.625936e+09183.396148194.044480-1.4212924.893770-8.3543659.682170
    1.625936e+09183.414273194.013538-1.4209844.893770-8.3543659.682170
    1.625936e+09183.432398193.982596-1.4206764.893770-8.3543659.682170
    1.625936e+09183.450524193.951654-1.4203684.893770-8.3543659.682170
    1.625936e+09183.468649193.920712-1.4200594.893770-8.3543659.682170
    .....................
    1.625937e+0938.376407113.604645-1.433903-0.0670770.0267830.072226
    1.625937e+0938.376407113.610601-1.434247-0.0808490.0431720.091653
    1.625937e+0938.376407113.616556-1.434589-0.0931160.0582590.109840
    1.625937e+0938.376407113.622511-1.434930-0.1039350.0720670.126476
    1.625937e+0938.376407113.628467-1.371597-0.1133660.0846190.141464
    \n", + "

    365438 rows × 6 columns

    \n", + "
    " + ], + "text/plain": [ + " position_x position_y orientation velocity_x velocity_y \\\n", + "time \n", + "1.625936e+09 183.396148 194.044480 -1.421292 4.893770 -8.354365 \n", + "1.625936e+09 183.414273 194.013538 -1.420984 4.893770 -8.354365 \n", + "1.625936e+09 183.432398 193.982596 -1.420676 4.893770 -8.354365 \n", + "1.625936e+09 183.450524 193.951654 -1.420368 4.893770 -8.354365 \n", + "1.625936e+09 183.468649 193.920712 -1.420059 4.893770 -8.354365 \n", + "... ... ... ... ... ... \n", + "1.625937e+09 38.376407 113.604645 -1.433903 -0.067077 0.026783 \n", + "1.625937e+09 38.376407 113.610601 -1.434247 -0.080849 0.043172 \n", + "1.625937e+09 38.376407 113.616556 -1.434589 -0.093116 0.058259 \n", + "1.625937e+09 38.376407 113.622511 -1.434930 -0.103935 0.072067 \n", + "1.625937e+09 38.376407 113.628467 -1.371597 -0.113366 0.084619 \n", + "\n", + " speed \n", + "time \n", + "1.625936e+09 9.682170 \n", + "1.625936e+09 9.682170 \n", + "1.625936e+09 9.682170 \n", + "1.625936e+09 9.682170 \n", + "1.625936e+09 9.682170 \n", + "... ... \n", + "1.625937e+09 0.072226 \n", + "1.625937e+09 0.091653 \n", + "1.625937e+09 0.109840 \n", + "1.625937e+09 0.126476 \n", + "1.625937e+09 0.141464 \n", + "\n", + "[365438 rows x 6 columns]" + ] + }, + "execution_count": 9, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "from spyglass.position import PositionOutput\n", + "\n", + "position_merge_id = (\n", + " PositionOutput.TrodesPosV1\n", + " & {\n", + " \"nwb_file_name\": nwb_copy_file_name,\n", + " \"interval_list_name\": \"pos 0 valid times\",\n", + " \"trodes_pos_params_name\": \"default_decoding\",\n", + " }\n", + ").fetch1(\"merge_id\")\n", + "\n", + "position_info = (\n", + " (PositionOutput & {\"merge_id\": position_merge_id})\n", + " .fetch1_dataframe()\n", + " .dropna()\n", + ")\n", + "position_info" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[2024-01-29 13:51:42,682][WARNING]: Skipped checksum for file with hash: 148d9058-e6dc-e959-4c4d-75db9aa0b6e4, and path: /Users/edeno/Documents/GitHub/spyglass/DATA/analysis/mediumnwb20230802/mediumnwb20230802_EF6N6XI3AH.nwb\n", + "[2024-01-29 13:51:43,058][WARNING]: Skipped checksum for file with hash: b4b6404f-aaf8-c4cc-9abe-ceea56e103f3, and path: /Users/edeno/Documents/GitHub/spyglass/DATA/analysis/mediumnwb20230802/mediumnwb20230802_O7ZZ0F1XN7.nwb\n", + "[2024-01-29 13:51:43,392][WARNING]: Skipped checksum for file with hash: 4357905c-c6b9-3990-4d62-740a54cfc667, and path: /Users/edeno/Documents/GitHub/spyglass/DATA/analysis/mediumnwb20230802/mediumnwb20230802_X84BYVM2B0.nwb\n", + "[2024-01-29 13:51:43,770][WARNING]: Skipped checksum for file with hash: ff81d274-17f7-702d-a2b4-92ac43c29316, and path: /Users/edeno/Documents/GitHub/spyglass/DATA/analysis/mediumnwb20230802/mediumnwb20230802_Y2YF504C5D.nwb\n", + "[2024-01-29 13:51:44,190][WARNING]: Skipped checksum for file with hash: 8993754e-7dbe-94a1-403d-8c55aa9c6c42, and path: /Users/edeno/Documents/GitHub/spyglass/DATA/analysis/mediumnwb20230802/mediumnwb20230802_JN4A4GSLZB.nwb\n", + "[2024-01-29 13:51:44,536][WARNING]: Skipped checksum for file with hash: 7d05460d-7366-27c9-2ba7-de2ad5d402f2, and path: /Users/edeno/Documents/GitHub/spyglass/DATA/analysis/mediumnwb20230802/mediumnwb20230802_4JXWFJ3JRI.nwb\n", + "[2024-01-29 13:51:44,845][WARNING]: Skipped checksum for file with hash: 6629fd95-636a-4ad4-c9af-cee507de2130, and path: /Users/edeno/Documents/GitHub/spyglass/DATA/analysis/mediumnwb20230802/mediumnwb20230802_AMBBKQ9RIY.nwb\n", + "[2024-01-29 13:51:45,223][WARNING]: Skipped checksum for file with hash: fa76d419-77a4-697a-325d-5c2ddbe517f9, and path: /Users/edeno/Documents/GitHub/spyglass/DATA/analysis/mediumnwb20230802/mediumnwb20230802_0R6AWXMC6G.nwb\n", + "[2024-01-29 13:51:45,600][WARNING]: Skipped checksum for file with hash: f64f34ee-e72d-e566-a048-65f2ea31708a, and path: /Users/edeno/Documents/GitHub/spyglass/DATA/analysis/mediumnwb20230802/mediumnwb20230802_USMRXAAV8I.nwb\n", + "[2024-01-29 13:51:45,991][WARNING]: Skipped checksum for file with hash: e282a8e5-844b-20f6-345c-cded12e761a9, and path: /Users/edeno/Documents/GitHub/spyglass/DATA/analysis/mediumnwb20230802/mediumnwb20230802_DUNM1TZUGR.nwb\n", + "[2024-01-29 13:51:46,369][WARNING]: Skipped checksum for file with hash: d740eb7d-ce29-e140-06a2-c56655e0842a, and path: /Users/edeno/Documents/GitHub/spyglass/DATA/analysis/mediumnwb20230802/mediumnwb20230802_L92EE1VRPB.nwb\n", + "[2024-01-29 13:51:46,765][WARNING]: Skipped checksum for file with hash: e43f95ff-9779-b980-00a3-99e104864462, and path: /Users/edeno/Documents/GitHub/spyglass/DATA/analysis/mediumnwb20230802/mediumnwb20230802_AKOI7OTASI.nwb\n", + "[2024-01-29 13:51:47,172][WARNING]: Skipped checksum for file with hash: 6d04cbdb-e1e4-f44f-7274-0e1ab0356d75, and path: /Users/edeno/Documents/GitHub/spyglass/DATA/analysis/mediumnwb20230802/mediumnwb20230802_W1MLF0Q86S.nwb\n", + "[2024-01-29 13:51:47,527][WARNING]: Skipped checksum for file with hash: 9e24661c-b021-6ad4-f224-89e331334f18, and path: /Users/edeno/Documents/GitHub/spyglass/DATA/analysis/mediumnwb20230802/mediumnwb20230802_T2DBO3EMZ8.nwb\n", + "[2024-01-29 13:51:47,895][WARNING]: Skipped checksum for file with hash: 1f386cd3-89da-0233-03ff-76ba94e91a3a, and path: /Users/edeno/Documents/GitHub/spyglass/DATA/analysis/mediumnwb20230802/mediumnwb20230802_TX2ZX3DAP4.nwb\n", + "[2024-01-29 13:51:48,301][WARNING]: Skipped checksum for file with hash: fde8b240-6adc-86f0-6391-f3f6fad72ee9, and path: /Users/edeno/Documents/GitHub/spyglass/DATA/analysis/mediumnwb20230802/mediumnwb20230802_HWU3E4EKP4.nwb\n", + "[2024-01-29 13:51:48,671][WARNING]: Skipped checksum for file with hash: 6d13e338-41bd-b011-beb5-4de53d9d467b, and path: /Users/edeno/Documents/GitHub/spyglass/DATA/analysis/mediumnwb20230802/mediumnwb20230802_JA2OA12RPN.nwb\n", + "[2024-01-29 13:51:49,020][WARNING]: Skipped checksum for file with hash: c202eb9e-ca43-0a72-4086-57a5bb6eb937, and path: /Users/edeno/Documents/GitHub/spyglass/DATA/analysis/mediumnwb20230802/mediumnwb20230802_5TY04H3B5T.nwb\n", + "[2024-01-29 13:51:49,400][WARNING]: Skipped checksum for file with hash: 26f7bdc7-da8d-6ad5-3f4a-554ceb48755e, and path: /Users/edeno/Documents/GitHub/spyglass/DATA/analysis/mediumnwb20230802/mediumnwb20230802_0TKF5589B7.nwb\n", + "[2024-01-29 13:51:49,798][WARNING]: Skipped checksum for file with hash: 023c874f-8114-3ef6-7fcf-813844787d5f, and path: /Users/edeno/Documents/GitHub/spyglass/DATA/analysis/mediumnwb20230802/mediumnwb20230802_L7HDY9IDHO.nwb\n", + "[2024-01-29 13:51:50,175][WARNING]: Skipped checksum for file with hash: ce4cb0c3-3dd0-70fd-8ea0-98a8b84592d9, and path: /Users/edeno/Documents/GitHub/spyglass/DATA/analysis/mediumnwb20230802/mediumnwb20230802_7UIA2ILMG6.nwb\n", + "[2024-01-29 13:51:50,560][WARNING]: Skipped checksum for file with hash: c592e63b-4db1-40be-632e-0180e6fa02d7, and path: /Users/edeno/Documents/GitHub/spyglass/DATA/analysis/mediumnwb20230802/mediumnwb20230802_SGAU9PX7US.nwb\n", + "[2024-01-29 13:51:50,963][WARNING]: Skipped checksum for file with hash: 4c1103ac-eaca-b282-e5ff-aa2194e65a43, and path: /Users/edeno/Documents/GitHub/spyglass/DATA/analysis/mediumnwb20230802/mediumnwb20230802_2R6VQ8EDL4.nwb\n" + ] + }, + { + "data": { + "text/plain": [ + "array([[0., 0., 0., ..., 0., 1., 0.],\n", + " [0., 0., 0., ..., 0., 0., 0.],\n", + " [0., 0., 0., ..., 0., 1., 1.],\n", + " ...,\n", + " [0., 1., 0., ..., 0., 0., 0.],\n", + " [0., 0., 0., ..., 0., 0., 0.],\n", + " [0., 0., 0., ..., 0., 0., 0.]])" + ] + }, + "execution_count": 10, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "time_ind_slice = slice(63_000, 70_000)\n", + "time = position_info.index[time_ind_slice]\n", + "\n", + "SortedSpikesGroup.get_spike_indicator(group_key, time)" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[2024-01-29 13:51:51,323][WARNING]: Skipped checksum for file with hash: 148d9058-e6dc-e959-4c4d-75db9aa0b6e4, and path: /Users/edeno/Documents/GitHub/spyglass/DATA/analysis/mediumnwb20230802/mediumnwb20230802_EF6N6XI3AH.nwb\n", + "[2024-01-29 13:51:51,656][WARNING]: Skipped checksum for file with hash: b4b6404f-aaf8-c4cc-9abe-ceea56e103f3, and path: /Users/edeno/Documents/GitHub/spyglass/DATA/analysis/mediumnwb20230802/mediumnwb20230802_O7ZZ0F1XN7.nwb\n", + "[2024-01-29 13:51:52,034][WARNING]: Skipped checksum for file with hash: 4357905c-c6b9-3990-4d62-740a54cfc667, and path: /Users/edeno/Documents/GitHub/spyglass/DATA/analysis/mediumnwb20230802/mediumnwb20230802_X84BYVM2B0.nwb\n", + "[2024-01-29 13:51:52,374][WARNING]: Skipped checksum for file with hash: ff81d274-17f7-702d-a2b4-92ac43c29316, and path: /Users/edeno/Documents/GitHub/spyglass/DATA/analysis/mediumnwb20230802/mediumnwb20230802_Y2YF504C5D.nwb\n", + "[2024-01-29 13:51:52,694][WARNING]: Skipped checksum for file with hash: 8993754e-7dbe-94a1-403d-8c55aa9c6c42, and path: /Users/edeno/Documents/GitHub/spyglass/DATA/analysis/mediumnwb20230802/mediumnwb20230802_JN4A4GSLZB.nwb\n", + "[2024-01-29 13:51:53,025][WARNING]: Skipped checksum for file with hash: 7d05460d-7366-27c9-2ba7-de2ad5d402f2, and path: /Users/edeno/Documents/GitHub/spyglass/DATA/analysis/mediumnwb20230802/mediumnwb20230802_4JXWFJ3JRI.nwb\n", + "[2024-01-29 13:51:53,389][WARNING]: Skipped checksum for file with hash: 6629fd95-636a-4ad4-c9af-cee507de2130, and path: /Users/edeno/Documents/GitHub/spyglass/DATA/analysis/mediumnwb20230802/mediumnwb20230802_AMBBKQ9RIY.nwb\n", + "[2024-01-29 13:51:53,744][WARNING]: Skipped checksum for file with hash: fa76d419-77a4-697a-325d-5c2ddbe517f9, and path: /Users/edeno/Documents/GitHub/spyglass/DATA/analysis/mediumnwb20230802/mediumnwb20230802_0R6AWXMC6G.nwb\n", + "[2024-01-29 13:51:54,114][WARNING]: Skipped checksum for file with hash: f64f34ee-e72d-e566-a048-65f2ea31708a, and path: /Users/edeno/Documents/GitHub/spyglass/DATA/analysis/mediumnwb20230802/mediumnwb20230802_USMRXAAV8I.nwb\n", + "[2024-01-29 13:51:54,482][WARNING]: Skipped checksum for file with hash: e282a8e5-844b-20f6-345c-cded12e761a9, and path: /Users/edeno/Documents/GitHub/spyglass/DATA/analysis/mediumnwb20230802/mediumnwb20230802_DUNM1TZUGR.nwb\n", + "[2024-01-29 13:51:54,884][WARNING]: Skipped checksum for file with hash: d740eb7d-ce29-e140-06a2-c56655e0842a, and path: /Users/edeno/Documents/GitHub/spyglass/DATA/analysis/mediumnwb20230802/mediumnwb20230802_L92EE1VRPB.nwb\n", + "[2024-01-29 13:51:55,251][WARNING]: Skipped checksum for file with hash: e43f95ff-9779-b980-00a3-99e104864462, and path: /Users/edeno/Documents/GitHub/spyglass/DATA/analysis/mediumnwb20230802/mediumnwb20230802_AKOI7OTASI.nwb\n", + "[2024-01-29 13:51:55,600][WARNING]: Skipped checksum for file with hash: 6d04cbdb-e1e4-f44f-7274-0e1ab0356d75, and path: /Users/edeno/Documents/GitHub/spyglass/DATA/analysis/mediumnwb20230802/mediumnwb20230802_W1MLF0Q86S.nwb\n", + "[2024-01-29 13:51:55,989][WARNING]: Skipped checksum for file with hash: 9e24661c-b021-6ad4-f224-89e331334f18, and path: /Users/edeno/Documents/GitHub/spyglass/DATA/analysis/mediumnwb20230802/mediumnwb20230802_T2DBO3EMZ8.nwb\n", + "[2024-01-29 13:51:56,379][WARNING]: Skipped checksum for file with hash: 1f386cd3-89da-0233-03ff-76ba94e91a3a, and path: /Users/edeno/Documents/GitHub/spyglass/DATA/analysis/mediumnwb20230802/mediumnwb20230802_TX2ZX3DAP4.nwb\n", + "[2024-01-29 13:51:56,740][WARNING]: Skipped checksum for file with hash: fde8b240-6adc-86f0-6391-f3f6fad72ee9, and path: /Users/edeno/Documents/GitHub/spyglass/DATA/analysis/mediumnwb20230802/mediumnwb20230802_HWU3E4EKP4.nwb\n", + "[2024-01-29 13:51:57,159][WARNING]: Skipped checksum for file with hash: 6d13e338-41bd-b011-beb5-4de53d9d467b, and path: /Users/edeno/Documents/GitHub/spyglass/DATA/analysis/mediumnwb20230802/mediumnwb20230802_JA2OA12RPN.nwb\n", + "[2024-01-29 13:51:57,506][WARNING]: Skipped checksum for file with hash: c202eb9e-ca43-0a72-4086-57a5bb6eb937, and path: /Users/edeno/Documents/GitHub/spyglass/DATA/analysis/mediumnwb20230802/mediumnwb20230802_5TY04H3B5T.nwb\n", + "[2024-01-29 13:51:57,880][WARNING]: Skipped checksum for file with hash: 26f7bdc7-da8d-6ad5-3f4a-554ceb48755e, and path: /Users/edeno/Documents/GitHub/spyglass/DATA/analysis/mediumnwb20230802/mediumnwb20230802_0TKF5589B7.nwb\n", + "[2024-01-29 13:51:58,241][WARNING]: Skipped checksum for file with hash: 023c874f-8114-3ef6-7fcf-813844787d5f, and path: /Users/edeno/Documents/GitHub/spyglass/DATA/analysis/mediumnwb20230802/mediumnwb20230802_L7HDY9IDHO.nwb\n", + "[2024-01-29 13:51:58,599][WARNING]: Skipped checksum for file with hash: ce4cb0c3-3dd0-70fd-8ea0-98a8b84592d9, and path: /Users/edeno/Documents/GitHub/spyglass/DATA/analysis/mediumnwb20230802/mediumnwb20230802_7UIA2ILMG6.nwb\n", + "[2024-01-29 13:51:58,991][WARNING]: Skipped checksum for file with hash: c592e63b-4db1-40be-632e-0180e6fa02d7, and path: /Users/edeno/Documents/GitHub/spyglass/DATA/analysis/mediumnwb20230802/mediumnwb20230802_SGAU9PX7US.nwb\n", + "[2024-01-29 13:51:59,349][WARNING]: Skipped checksum for file with hash: 4c1103ac-eaca-b282-e5ff-aa2194e65a43, and path: /Users/edeno/Documents/GitHub/spyglass/DATA/analysis/mediumnwb20230802/mediumnwb20230802_2R6VQ8EDL4.nwb\n" + ] + }, + { + "data": { + "text/plain": [ + "Text(0.5, 0, 'time (s)')" + ] + }, + "execution_count": 11, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "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ipdeegmzZs2K6ffb29vR3d2N6upqdoWkgmC1WtHR0YHu7u6obZGJ8h33dyo23Oep2HCfp2LDfZ6KSa7u75IkYWJiAu3t7VEfq5NiyY8jooJjtVpRW1sLi8WSUwMYUTpwf6diw32eig33eSo23OepmBTC/l5U3U6JiIiIiIiIiIgyicE3IiIiIiIiIiKiNGHwjahImUwm3HnnnTCZTNneFKK04/5OxYb7PBUb7vNUbLjPUzEphP2dNd+IiIiIiIiIiIjShJlvREREREREREREacLgGxERERERERERUZow+EZERERERERERJQmDL4RERERERERERGlCYNvREREREREREREacLgGxERERERERERUZow+EZERERERERERJQmDL4RERERERERERGlCYNvREREREREREREacLgGxERERERERERUZow+EZERERERERERJQmDL4RERERERERERGlCYNvREREREREREREacLgGxERERERERERUZow+EZERERERERERJQmDL4RERERERERERGlCYNvREREREREREREacLgGxERERERERERUZow+EZERERERERERJQmDL4RERERERERERGlSUm2NyBfiKKIvr4+VFdXQ6fTZXtziIiIiIiIiIgoSyRJwsTEBNrb26HXR85tY/AtRn19fejo6Mj2ZhARERERERERUY7o7u7GjBkzIj6GwbcYVVdXA/C/qTU1NVneGiIiIiIiIiIiyhar1YqOjg4lXhQJg28xkpea1tTUMPhGREREREREREQxlSZjwwUiIiIiIiIiIqI0YfCNiIiIiIiIiIgoTRh8IyIiIiIiIiIqQD6fD5IkZXszih5rvhERERERERERFRBJktDb24vx8XEYDAZ0dnaivLw825tVtJj5RkRERERERERUQAYGBjA+Pg4AEAQBXV1dEAQhuxtVxBh8IyIiIiIiIiIqEE6nE6Ojo5rbfD5f0G2UOQy+EREREREREREViIGBgZC3j46Osv5bljD4RkREREQJEwQBDoeDJ/NEREQ5wOFwwG63h7xPEATYbLYMbxEBbLhARERERAlyu93Yt28fBEFARUUFOjs7odfz2i4REVG2DA0NRbzfYrGguro6Q1tDMp4dEREREVHcJElCd3e3UrzZ4XBgZGQky1tFuc7tdsPj8WR7M4iI8oIkSbBYLBgYGMDQ0BBcLlfExzud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tzKxeTnD4/FgcHAwLTUmogVxvF4vRkdHk2pRbbFYYpqAejyelJ2gF/LJUbwBRUEQ0NXVFfZ+p9OZUBtzItJyuVzo7e1Fb29vtjeFKGcw8EaplMpzxXgw0EJq3B+ICktRBN9kgct05KWPodx222246aablJ/lzLdCUl9fH/I9cTqd8Hq9MBqNSn2gTHE6ndDpdMryxXi53W5lOSplliiKsFqtETutSpIEh8MBj8cDURRRWlqKysrKgmjUQZRJXq8XVqsVer1eWdZORESpIV9c5fkJEVHqqeuRF5OiiFA0NTXBYDAEZbkNDQ2F7JAF+OuHxNJZLp+Vl5dnPLhGhW369OnZ3gQiIiIiIiKinFIUl8qNRiOOOuoovPrqq5rbX331VaxatSpLW0VERERERERERIWuKDLfAOCmm27CpZdeiuXLl2PlypV47LHHcPDgQVx99dXZ3jQiIiIiIiIiIipQRRN8u+iiizA6Ooq77roL/f39WLp0KV566SXMmjUr25tGREREREREREQFSifF29KwSFksFtTV1aG7uztqC1kiIiIiIiIiIipccmPO8fHxqI0kiibzLVkTExMAUHAdT4mIiIiIiIiIKDETExNRg2/MfIuRKIro6+tDdXU1dDpdtjeHKGlylJ7ZnFQMuL9TseE+T8WG+zwVG+7zVExydX+XJAkTExNob2+HXh+5nykz32Kk1+sxY8aMbG8GUcrV1NTk1ABGlE7c36nYcJ+nYsN9nooN93kqJrm4v0fLeJNFDs0RERERERERERFRwhh8IyIiIiIiIiIiShMG34iKlMlkwp133gmTyZTtTSFKO+7vVGy4z1Ox4T5PxYb7PBWTQtjf2XCBiIiIiIiIiIgoTZj5RkRERERERERElCYMvhEREREREREREaUJg29ERERERERERERpwuAbERERERERERFRmjD4RlTAOjs7odPpgv5de+21AABJkrB582a0t7ejvLwca9aswUcffZTlrSZKXLR9fuPGjUH3HXvssVneaqLE+Hw+fPOb38Ts2bNRXl6OOXPm4K677oIoispjOM5TIYlln+c4T4VmYmICmzZtwqxZs1BeXo5Vq1bhnXfeUe7nOE+FJNr+ns9jPINvRAXsnXfeQX9/v/Lv1VdfBQBccMEFAID7778fW7duxcMPP4x33nkHra2tOPXUUzExMZHNzSZKWLR9HgBOO+00zWNeeumlbG0uUVLuu+8+/PCHP8TDDz+MTz75BPfffz8eeOABfP/731cew3GeCkks+zzAcZ4Ky5VXXolXX30VTz31FD788EOsXbsWp5xyCnp7ewFwnKfCEm1/B/J3jNdJkiRleyOIKDM2bdqE3/72t9i9ezcAoL29HZs2bcLXvvY1AIDb7UZLSwvuu+8+fOUrX8nmphKlhHqf1+l02LhxI8bHx/HCCy9ke9OIknbWWWehpaUF//M//6Pcdt5556GiogJPPfUUJEniOE8FJdo+D4DjPBUUp9OJ6upq/N///R/OPPNM5fYjjjgCZ511Fu6++26O81Qwou3v3/72t/N6jGfmG1GR8Hg8+NnPfoYvfvGL0Ol02L9/PwYGBrB27VrlMSaTCSeeeCLeeuutLG4pUWoE7vOy119/Hc3NzViwYAGuuuoqDA0NZXEriRJ33HHH4U9/+hN27doFAPjggw/w5ptv4owzzgAAjvNUcKLt8zKO81QofD4fBEFAWVmZ5vby8nK8+eabHOepoETb32X5OsaXZHsDiCgzXnjhBYyPj2Pjxo0AgIGBAQBAS0uL5nEtLS3o6urK9OYRpVzgPg8Ap59+Oi644ALMmjUL+/fvxx133IHPfOYz2L59O0wmU/Y2ligBX/va12CxWLBw4UIYDAYIgoB77rkHF198MQCO81R4ou3zAMd5KizV1dVYuXIl7r77bixatAgtLS14+umn8c9//hPz58/nOE8FJdr+DuT3GM/gG1GR+J//+R+cfvrpaG9v19yuzggC/EVbA28jykeh9vmLLrpI+f/SpUuxfPlyzJo1C7/73e+wbt26bGwmUcJ++ctf4mc/+xl+8YtfYMmSJXj//fexadMmtLe34/LLL1cex3GeCkUs+zzHeSo0Tz31FL74xS9i+vTpMBgMOPLII7F+/Xrs2LFDeQzHeSoU0fb3fB7jGXwjKgJdXV344x//iOeee065rbW1FYA/M6KtrU25fWhoKOjqGVG+CbXPh9LW1oZZs2YpdRCJ8sktt9yCr3/96/jCF74AADj00EPR1dWFe++9F5dffjnHeSo40fb5UDjOU76bO3cu3njjDdjtdlitVrS1teGiiy7C7NmzOc5TwYm0v4eST2M8a74RFYFt27ahublZU7hSPmDL3SABf42sN954A6tWrcrGZhKlTKh9PpTR0VF0d3drTliJ8oXD4YBerz2VMxgMEEURAMd5KjzR9vlQOM5ToaisrERbWxvMZjNefvllnHPOORznqWCF2t9DyacxnplvRAVOFEVs27YNl19+OUpKpr7yOp0OmzZtwpYtWzB//nzMnz8fW7ZsQUVFBdavX5/FLSZKTrh93mazYfPmzTjvvPPQ1taGAwcO4Bvf+Aaamppw7rnnZnGLiRLzuc99Dvfccw9mzpyJJUuW4L333sPWrVvxxS9+EQDHeSo80fZ5jvNUiF5++WVIkoRDDjkEe/bswS233IJDDjkEV1xxBcd5KjiR9ve8H+MlIipoL7/8sgRA2rlzZ9B9oihKd955p9Ta2iqZTCbphBNOkD788MMsbCVR6oTb5x0Oh7R27Vpp2rRpUmlpqTRz5kzp8ssvlw4ePJilLSVKjtVqlW644QZp5syZUllZmTRnzhzp9ttvl9xut/IYjvNUSKLt8xznqRD98pe/lObMmSMZjUaptbVVuvbaa6Xx8XHlfo7zVEgi7e/5PsbrJEmSsh0AJCIiIiIiIiIiKkSs+UZERERERERERJQmDL4RERERERERERGlCYNvREREREREREREacLgGxERERERERERUZow+EZERERERERERJQmDL4RERERERERERGlCYNvREREREREREREacLgGxERERERERFRAXjsscewZs0a1NTUQKfTYXx8PKbf6+3txYYNG9DY2IiKigocccQR2L59OwDA6/Xia1/7Gg499FBUVlaivb0dl112Gfr6+jTPsWbNGuh0Os2/L3zhC5rH7NixA6eeeirq6urQ2NiIL3/5y7DZbMr9o6OjOO2009De3g6TyYSOjg5cd911sFqtymMOHDgQ9Do6nQ5/+MMfNK/1gx/8AIsWLUJ5eTkOOeQQ/PSnP43nrYxpe2PF4BsRERFRAXv99dfjOvlOtT//+c9YuHAhRFGM+tjf/va3WLZsWUyPJSIiKlZr1qzBE088EfI+h8OB0047Dd/4xjdifj6z2YzVq1ejtLQUv//97/Hxxx/jwQcfRF1dnfKcO3bswB133IEdO3bgueeew65du3D22WcHPddVV12F/v5+5d+PfvQj5b6+vj6ccsopmDdvHv75z3/iD3/4Az766CNs3LhReYxer8c555yDF198Ebt27cITTzyBP/7xj7j66quDXuuPf/yj5rU+85nPKPc9+uijuO2227B582Z89NFH+Na3voVrr70Wv/nNb2J+X2LZ3ljpJEmS4v4tIiIiIso5a9aswRFHHIGHHnpIuc3j8WBsbAwtLS3Q6XQZ36bly5fjhhtuwKWXXhrT44888kjcdNNN2LBhQ5q3jIiIKD+tWbMGGzdujBgEev3113HSSSfBbDYrQbRwvv71r+Nvf/sb/vrXv8a8De+88w6OOeYYdHV1YebMmcp2BZ6HqD322GO444470N/fD73enwv2/vvvY9myZdi9ezfmzZsX8vf++7//Gw888AC6u7sB+DPfZs+ejffeew9HHHFEyN9ZtWoVVq9ejQceeEC5bdOmTXj33Xfx5ptvKrdt27YN999/P/bv34/Ozk5cf/31uOaaa5La3lCY+UZERERUwIxGI1pbW7MSeHvrrbewe/duXHDBBTH/zhVXXIHvf//7adwqIiIiUnvxxRexfPlyXHDBBWhubsayZcvw+OOPR/wdi8UCnU4XFNj7+c9/jqamJixZsgQ333wzJiYmlPvcbjeMRqMSyAKA8vJyANAExNT6+vrw3HPP4cQTTwy67+yzz0ZzczNWr16NZ599VnOf2+1GWVmZ5rby8nK8/fbb8Hq9AIDHH38ct99+O+655x588skn2LJlC+644w48+eSTCW9vOAy+ERERERWAjRs34o033sD3vvc9pfbJgQMHgpadPvHEE6irq8Nvf/tbHHLIIaioqMD5558Pu92OJ598Ep2dnaivr8d//ud/QhAE5fk9Hg9uvfVWTJ8+HZWVlVixYgVef/31iNv0zDPPYO3atZqT3w8++AAnnXQSqqurUVNTg6OOOgrvvvuucv/ZZ5+Nt99+G/v27Uvp+0NERESh7du3D48++ijmz5+Pl19+GVdffTWuv/76sDXSXC4Xvv71r2P9+vWoqalRbr/kkkvw9NNP4/XXX8cdd9yBX//611i3bp1y/2c+8xkMDAzggQcegMfjgdlsVpbH9vf3a17j4osvRkVFBaZPn46amhr8+Mc/Vu6rqqrC1q1b8eyzz+Kll17CySefjIsuugg/+9nPlMd89rOfxY9//GNs374dkiTh3XffxU9+8hN4vV6MjIwAAO6++248+OCDWLduHWbPno1169bhxhtvVJbKxrO9UUlERERElPfGx8ellStXSldddZXU398v9ff3Sz6fT3rttdckAJLZbJYkSZK2bdsmlZaWSqeeeqq0Y8cO6Y033pAaGxultWvXShdeeKH00UcfSb/5zW8ko9EoPfPMM8rzr1+/Xlq1apX0l7/8RdqzZ4/0wAMPSCaTSdq1a1fYbTr88MOl73znO5rblixZIm3YsEH65JNPpF27dkm/+tWvpPfff1/zmObmZumJJ55I3ZtDRESUx+655x6psrJS+afX6yWTyaS57S9/+YvmdwKP/5GUlpZKK1eu1Nz2n//5n9Kxxx4b9FiPxyOdc8450rJlyySLxRLxed99910JgLR9+3bltp///OdSS0uLZDAYJKPRKN18881SS0uLdN9992l+t7+/X/rkk0+kF154QVq8eLH0H//xHxFf67rrrpMOPfRQ5WeHwyFdccUVUklJiWQwGKT29nbp1ltvlQBIg4OD0tDQkARAKi8v17yPJpNJam5ujnt7oymJL1RHRERERLmotrYWRqMRFRUVaG1tjfhYr9eLRx99FHPnzgUAnH/++XjqqacwODiIqqoqLF68GCeddBJee+01XHTRRdi7dy+efvpp9PT0oL29HQBw88034w9/+AO2bduGLVu2hHydAwcOKI+XHTx4ELfccgsWLlwIAJg/f37Q702fPh0HDhyI9y0gIiIqSFdffTUuvPBC5edLLrkE5513niarbPr06Qk/f1tbGxYvXqy5bdGiRfj1r3+tuc3r9eLCCy/E/v378ec//1mT9RbKkUceidLSUuzevRtHHnkkAGD9+vVYv349BgcHUVlZCZ1Oh61bt2L27Nma321tbUVraysWLlyIxsZGHH/88bjjjjvQ1tYW8rWOPfZYTXZceXk5fvKTn+BHP/oRBgcH0dbWhsceewzV1dVoamrC8PAwAP/S0xUrVmiey2AwKP+PdXujYfCNiIiIqMhUVFQogTcAaGlpQWdnJ6qqqjS3DQ0NAQB27NgBSZKwYMECzfO43W40NjaGfR2n0xlUb+Wmm27ClVdeiaeeegqnnHIKLrjgAs22AP4TZofDkfDfR0REVEgaGhrQ0NCg/FxeXo7m5ua4Cv5Hsnr1auzcuVNz265duzBr1izlZznwtnv3brz22msRj/+yjz76CF6vN2TArKWlBQDwk5/8BGVlZTj11FPDPo802SfU7XaHfcx7770X8nVKS0sxY8YMAP5yGGeddRb0ej1aWlowffp07Nu3D5dccknUvyWe7Q2FwTciIiKiIlNaWqr5WafThbxNFEUAgCiKMBgM2L59u+ZqMABNwC5QU1MTzGaz5rbNmzdj/fr1+N3vfoff//73uPPOO/HMM8/g3HPPVR4zNjaGadOmJfS3ERERFbOBgQEMDAxgz549AIAPP/wQ1dXVmDlzphLAO/nkk3HuuefiuuuuAwDceOONWLVqFbZs2YILL7wQb7/9Nh577DE89thjAACfz4fzzz8fO3bswG9/+1sIgoCBgQEA/sCg0WjE3r178fOf/xxnnHEGmpqa8PHHH+OrX/0qli1bhtWrVyvb9/DDD2PVqlWoqqrCq6++iltuuQXf+c53lMYNL730EgYHB3H00UejqqoKH3/8MW699VasXr0anZ2dAIAnn3wSpaWlWLZsGfR6PX7zm9/gv//7v3Hfffcpr7Nr1y68/fbbWLFiBcxmM7Zu3Yp///vfSjMFwH9Ocv3116Ompgann3463G433n33XZjNZtx0000xbW+sGHwjIiIiKhBGo1HTJCFVli1bBkEQMDQ0hOOPPz6u3/v444+Dbl+wYAEWLFiAG2+8ERdffDG2bdumBN9cLhf27t2LZcuWpWz7iYiIisUPf/hDfOtb31J+PuGEEwAA27Ztw8aNGwEAe/fuVZoOAMDRRx+N559/HrfddhvuuusuzJ49Gw899JCSEdbT04MXX3wRAHDEEUdoXu+1117DmjVrYDQa8ac//Qnf+973YLPZ0NHRgTPPPBN33nmn5sLd22+/jTvvvBM2mw0LFy7Ej370I1x66aXK/eXl5Xj88cdx4403wu12o6OjA+vWrcPXv/51zet++9vfRldXFwwGAxYsWICf/OQn2LBhg3K/IAh48MEHsXPnTpSWluKkk07CW2+9pQTwAODKK69ERUUFHnjgAdx6662orKzEoYceik2bNsW8vbHSSXL+HhERERHltS9/+ct4//338atf/QpVVVVoaGjAX/7yF5x00kkwm82oq6vDE088gU2bNindTwH/ld8XXngB77//vnLbxo0bMT4+jhdeeAEAsGHDBvztb3/Dgw8+iGXLlmFkZAR//vOfceihh+KMM84IuT3f//738eSTTyrdTJ1OJ2655Racf/75mD17Nnp6enD55ZfjvPPOU65Wv/766/jc5z6HwcFBVFRUpOV9IiIiIsokfbY3gIiIiIhS4+abb4bBYMDixYsxbdo0HDx4MGXPvW3bNlx22WX46le/ikMOOQRnn302/vnPf6KjoyPs72zYsAEff/yxUkfGYDBgdHQUl112GRYsWIALL7wQp59+uuYK/dNPP41LLrmEgTciIiIqGMx8IyIiIqK0ufXWW2GxWPCjH/0o6mOHh4excOFCvPvuu3F3ESMiIiLKVcx8IyIiIqK0uf322zFr1qyYatHt378fjzzyCANvREREVFCY+UZERERERERERJQmzHwjIiIiIiIiIiJKEwbfiIiIiIiIiIiI0oTBNyIiIiIiIiIiojRh8I2IiIiIiIiIiChNGHwjIiIiIiIiIiJKEwbfiIiIiIiIiIiI0oTBNyIiIiIiIiIiojRh8I2IiIiIiIiIiChNGHwjIiIiIiIiIiJKk/8PKEKQ06nUAAYAAAAASUVORK5CYII=", + "text/plain": [ + "
    " + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "import matplotlib.pyplot as plt\n", + "\n", + "fig, axes = plt.subplots(2, 1, sharex=True, figsize=(15, 4))\n", + "multiunit_firing_rate = SortedSpikesGroup.get_firing_rate(\n", + " group_key, time, multiunit=True\n", + ")\n", + "axes[0].plot(\n", + " time,\n", + " multiunit_firing_rate,\n", + ")\n", + "axes[0].set_ylabel(\"firing rate (Hz)\")\n", + "axes[0].set_title(\"multiunit\")\n", + "axes[1].fill_between(\n", + " time, position_info[\"speed\"].iloc[time_ind_slice], color=\"lightgrey\"\n", + ")\n", + "axes[1].set_ylabel(\"speed (cm/s)\")\n", + "axes[1].set_xlabel(\"time (s)\")" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + "
    \n", + " \n", + " \n", + " \n", + "\n", + "
    \n", + "

    mua_param_name

    \n", + " a name for this set of parameters\n", + "
    \n", + "

    mua_param_dict

    \n", + " dictionary of parameters\n", + "
    default=BLOB=
    \n", + " \n", + "

    Total: 1

    \n", + " " + ], + "text/plain": [ + "*mua_param_nam mua_param_\n", + "+------------+ +--------+\n", + "default =BLOB= \n", + " (Total: 1)" + ] + }, + "execution_count": 12, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "from spyglass.mua.v1.mua import MuaEventsParameters, MuaEventsV1\n", + "\n", + "MuaEventsParameters().insert_default()\n", + "MuaEventsParameters()" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[13:51:59][WARNING] Spyglass: Upsampled position data, frame indices are invalid. Setting add_frame_ind=False\n", + "[2024-01-29 13:52:00,002][WARNING]: Skipped checksum for file with hash: 0cd40383-03e0-44ec-5dac-36c66063796a, and path: /Users/edeno/Documents/GitHub/spyglass/DATA/analysis/mediumnwb20230802/mediumnwb20230802_FUSH604NQA.nwb\n", + "[2024-01-29 13:52:00,421][WARNING]: Skipped checksum for file with hash: 148d9058-e6dc-e959-4c4d-75db9aa0b6e4, and path: /Users/edeno/Documents/GitHub/spyglass/DATA/analysis/mediumnwb20230802/mediumnwb20230802_EF6N6XI3AH.nwb\n", + "[2024-01-29 13:52:00,785][WARNING]: Skipped checksum for file with hash: b4b6404f-aaf8-c4cc-9abe-ceea56e103f3, and path: /Users/edeno/Documents/GitHub/spyglass/DATA/analysis/mediumnwb20230802/mediumnwb20230802_O7ZZ0F1XN7.nwb\n", + "[2024-01-29 13:52:01,131][WARNING]: Skipped checksum for file with hash: 4357905c-c6b9-3990-4d62-740a54cfc667, and path: /Users/edeno/Documents/GitHub/spyglass/DATA/analysis/mediumnwb20230802/mediumnwb20230802_X84BYVM2B0.nwb\n", + "[2024-01-29 13:52:01,498][WARNING]: Skipped checksum for file with hash: ff81d274-17f7-702d-a2b4-92ac43c29316, and path: /Users/edeno/Documents/GitHub/spyglass/DATA/analysis/mediumnwb20230802/mediumnwb20230802_Y2YF504C5D.nwb\n", + "[2024-01-29 13:52:01,888][WARNING]: Skipped checksum for file with hash: 8993754e-7dbe-94a1-403d-8c55aa9c6c42, and path: /Users/edeno/Documents/GitHub/spyglass/DATA/analysis/mediumnwb20230802/mediumnwb20230802_JN4A4GSLZB.nwb\n", + "[2024-01-29 13:52:02,230][WARNING]: Skipped checksum for file with hash: 7d05460d-7366-27c9-2ba7-de2ad5d402f2, and path: /Users/edeno/Documents/GitHub/spyglass/DATA/analysis/mediumnwb20230802/mediumnwb20230802_4JXWFJ3JRI.nwb\n", + "[2024-01-29 13:52:02,608][WARNING]: Skipped checksum for file with hash: 6629fd95-636a-4ad4-c9af-cee507de2130, and path: /Users/edeno/Documents/GitHub/spyglass/DATA/analysis/mediumnwb20230802/mediumnwb20230802_AMBBKQ9RIY.nwb\n", + "[2024-01-29 13:52:02,984][WARNING]: Skipped checksum for file with hash: fa76d419-77a4-697a-325d-5c2ddbe517f9, and path: /Users/edeno/Documents/GitHub/spyglass/DATA/analysis/mediumnwb20230802/mediumnwb20230802_0R6AWXMC6G.nwb\n", + "[2024-01-29 13:52:03,365][WARNING]: Skipped checksum for file with hash: f64f34ee-e72d-e566-a048-65f2ea31708a, and path: /Users/edeno/Documents/GitHub/spyglass/DATA/analysis/mediumnwb20230802/mediumnwb20230802_USMRXAAV8I.nwb\n", + "[2024-01-29 13:52:03,762][WARNING]: Skipped checksum for file with hash: e282a8e5-844b-20f6-345c-cded12e761a9, and path: /Users/edeno/Documents/GitHub/spyglass/DATA/analysis/mediumnwb20230802/mediumnwb20230802_DUNM1TZUGR.nwb\n", + "[2024-01-29 13:52:04,194][WARNING]: Skipped checksum for file with hash: d740eb7d-ce29-e140-06a2-c56655e0842a, and path: /Users/edeno/Documents/GitHub/spyglass/DATA/analysis/mediumnwb20230802/mediumnwb20230802_L92EE1VRPB.nwb\n", + "[2024-01-29 13:52:04,662][WARNING]: Skipped checksum for file with hash: e43f95ff-9779-b980-00a3-99e104864462, and path: /Users/edeno/Documents/GitHub/spyglass/DATA/analysis/mediumnwb20230802/mediumnwb20230802_AKOI7OTASI.nwb\n", + "[2024-01-29 13:52:05,074][WARNING]: Skipped checksum for file with hash: 6d04cbdb-e1e4-f44f-7274-0e1ab0356d75, and path: /Users/edeno/Documents/GitHub/spyglass/DATA/analysis/mediumnwb20230802/mediumnwb20230802_W1MLF0Q86S.nwb\n", + "[2024-01-29 13:52:05,558][WARNING]: Skipped checksum for file with hash: 9e24661c-b021-6ad4-f224-89e331334f18, and path: /Users/edeno/Documents/GitHub/spyglass/DATA/analysis/mediumnwb20230802/mediumnwb20230802_T2DBO3EMZ8.nwb\n", + "[2024-01-29 13:52:05,938][WARNING]: Skipped checksum for file with hash: 1f386cd3-89da-0233-03ff-76ba94e91a3a, and path: /Users/edeno/Documents/GitHub/spyglass/DATA/analysis/mediumnwb20230802/mediumnwb20230802_TX2ZX3DAP4.nwb\n", + "[2024-01-29 13:52:06,285][WARNING]: Skipped checksum for file with hash: fde8b240-6adc-86f0-6391-f3f6fad72ee9, and path: /Users/edeno/Documents/GitHub/spyglass/DATA/analysis/mediumnwb20230802/mediumnwb20230802_HWU3E4EKP4.nwb\n", + "[2024-01-29 13:52:06,641][WARNING]: Skipped checksum for file with hash: 6d13e338-41bd-b011-beb5-4de53d9d467b, and path: /Users/edeno/Documents/GitHub/spyglass/DATA/analysis/mediumnwb20230802/mediumnwb20230802_JA2OA12RPN.nwb\n", + "[2024-01-29 13:52:07,019][WARNING]: Skipped checksum for file with hash: c202eb9e-ca43-0a72-4086-57a5bb6eb937, and path: /Users/edeno/Documents/GitHub/spyglass/DATA/analysis/mediumnwb20230802/mediumnwb20230802_5TY04H3B5T.nwb\n", + "[2024-01-29 13:52:07,412][WARNING]: Skipped checksum for file with hash: 26f7bdc7-da8d-6ad5-3f4a-554ceb48755e, and path: /Users/edeno/Documents/GitHub/spyglass/DATA/analysis/mediumnwb20230802/mediumnwb20230802_0TKF5589B7.nwb\n", + "[2024-01-29 13:52:07,806][WARNING]: Skipped checksum for file with hash: 023c874f-8114-3ef6-7fcf-813844787d5f, and path: /Users/edeno/Documents/GitHub/spyglass/DATA/analysis/mediumnwb20230802/mediumnwb20230802_L7HDY9IDHO.nwb\n", + "[2024-01-29 13:52:08,189][WARNING]: Skipped checksum for file with hash: ce4cb0c3-3dd0-70fd-8ea0-98a8b84592d9, and path: /Users/edeno/Documents/GitHub/spyglass/DATA/analysis/mediumnwb20230802/mediumnwb20230802_7UIA2ILMG6.nwb\n", + "[2024-01-29 13:52:08,553][WARNING]: Skipped checksum for file with hash: c592e63b-4db1-40be-632e-0180e6fa02d7, and path: /Users/edeno/Documents/GitHub/spyglass/DATA/analysis/mediumnwb20230802/mediumnwb20230802_SGAU9PX7US.nwb\n", + "[2024-01-29 13:52:08,875][WARNING]: Skipped checksum for file with hash: 4c1103ac-eaca-b282-e5ff-aa2194e65a43, and path: /Users/edeno/Documents/GitHub/spyglass/DATA/analysis/mediumnwb20230802/mediumnwb20230802_2R6VQ8EDL4.nwb\n", + "/Users/edeno/miniconda3/envs/spyglass/lib/python3.9/site-packages/pynwb/ecephys.py:90: UserWarning: ElectricalSeries 'e-series': The second dimension of data does not match the length of electrodes. Your data may be transposed.\n", + " warnings.warn(\"%s '%s': The second dimension of data does not match the length of electrodes. \"\n", + "/Users/edeno/miniconda3/envs/spyglass/lib/python3.9/site-packages/pynwb/base.py:193: UserWarning: TimeSeries 'analog': Length of data does not match length of timestamps. Your data may be transposed. Time should be on the 0th dimension\n", + " warn(\"%s '%s': Length of data does not match length of timestamps. Your data may be transposed. \"\n", + "[13:52:10][INFO] Spyglass: Writing new NWB file mediumnwb20230802_0ADLJ3W6MJ.nwb\n" + ] + } + ], + "source": [ + "selection_key = {\n", + " \"mua_param_name\": \"default\",\n", + " \"nwb_file_name\": nwb_copy_file_name,\n", + " \"sorted_spikes_group_name\": \"test_group\",\n", + " \"pos_merge_id\": position_merge_id,\n", + " \"artifact_interval_list_name\": \"test_artifact_times\",\n", + "}\n", + "\n", + "MuaEventsV1.populate(selection_key)" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + "
    \n", + " \n", + " \n", + " \n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "
    \n", + "

    mua_param_name

    \n", + " a name for this set of parameters\n", + "
    \n", + "

    nwb_file_name

    \n", + " name of the NWB file\n", + "
    \n", + "

    sorted_spikes_group_name

    \n", + " \n", + "
    \n", + "

    pos_merge_id

    \n", + " \n", + "
    \n", + "

    artifact_interval_list_name

    \n", + " descriptive name of this interval list\n", + "
    \n", + "

    analysis_file_name

    \n", + " name of the file\n", + "
    \n", + "

    mua_times_object_id

    \n", + " \n", + "
    defaultmediumnwb20230802_.nwbtest_group6dfae23d-6034-e483-06e7-28ab4c29282ftest_artifact_timesmediumnwb20230802_0ADLJ3W6MJ.nwb56d076f9-8751-4cec-b7b4-21a14058fcff
    \n", + " \n", + "

    Total: 1

    \n", + " " + ], + "text/plain": [ + "*mua_param_nam *nwb_file_name *sorted_spikes *pos_merge_id *artifact_inte analysis_file_ mua_times_obje\n", + "+------------+ +------------+ +------------+ +------------+ +------------+ +------------+ +------------+\n", + "default mediumnwb20230 test_group 6dfae23d-6034- test_artifact_ mediumnwb20230 56d076f9-8751-\n", + " (Total: 1)" + ] + }, + "execution_count": 14, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "MuaEventsV1 & selection_key" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[2024-01-29 13:52:11,975][WARNING]: Skipped checksum for file with hash: 6b7e200d-7337-6c3e-ae61-b52ac7b9d6ca, and path: /Users/edeno/Documents/GitHub/spyglass/DATA/analysis/mediumnwb20230802/mediumnwb20230802_0ADLJ3W6MJ.nwb\n" + ] + }, + { + "data": { + "text/html": [ + "
    \n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
    start_timeend_timedurationmean_zscoremedian_zscoremax_zscoremin_zscorespeed_at_startspeed_at_endmax_speedmin_speedmedian_speedmean_speed
    id
    01.625936e+091.625936e+090.0840001.2509941.2255172.3462750.0269002.8457751.4424412.8457751.3523431.9788322.010321
    11.625936e+091.625936e+090.0680001.8671701.9945183.2431240.0614680.2875110.1166740.2875110.1166740.1841480.190783
    21.625936e+091.625936e+090.1280001.3084371.0480303.0132050.0226772.0975261.2618062.1313991.2618061.9450541.848956
    31.625936e+091.625936e+090.2600001.8470132.2257662.9791400.0281240.7939930.5237512.1964690.5237511.6970521.616889
    41.625936e+091.625936e+090.0920001.3202181.3678872.3771420.0218572.1399931.3046872.1399931.1423131.3215521.465801
    ..........................................
    2121.625937e+091.625937e+090.2280005.0200904.97621610.5399190.2398891.3363510.4412901.3363510.3896530.8283710.804487
    2131.625937e+091.625937e+090.3039994.8701604.9684718.5614970.1293860.9567870.4084020.9661320.1708950.4169610.540956
    2141.625937e+091.625937e+090.1400003.2504983.1461046.1574760.1228351.7450862.1990062.2621941.7450862.2020812.125525
    2151.625937e+091.625937e+090.0600002.1291162.2166163.7904660.1270671.3324291.0778091.3324291.0778091.2655361.242683
    2161.625937e+091.625937e+090.1040001.5469421.6816912.5946440.0070790.3695860.1850780.3758290.1839490.3032570.291096
    \n", + "

    217 rows × 13 columns

    \n", + "
    " + ], + "text/plain": [ + " start_time end_time duration mean_zscore median_zscore \\\n", + "id \n", + "0 1.625936e+09 1.625936e+09 0.084000 1.250994 1.225517 \n", + "1 1.625936e+09 1.625936e+09 0.068000 1.867170 1.994518 \n", + "2 1.625936e+09 1.625936e+09 0.128000 1.308437 1.048030 \n", + "3 1.625936e+09 1.625936e+09 0.260000 1.847013 2.225766 \n", + "4 1.625936e+09 1.625936e+09 0.092000 1.320218 1.367887 \n", + ".. ... ... ... ... ... \n", + "212 1.625937e+09 1.625937e+09 0.228000 5.020090 4.976216 \n", + "213 1.625937e+09 1.625937e+09 0.303999 4.870160 4.968471 \n", + "214 1.625937e+09 1.625937e+09 0.140000 3.250498 3.146104 \n", + "215 1.625937e+09 1.625937e+09 0.060000 2.129116 2.216616 \n", + "216 1.625937e+09 1.625937e+09 0.104000 1.546942 1.681691 \n", + "\n", + " max_zscore min_zscore speed_at_start speed_at_end max_speed \\\n", + "id \n", + "0 2.346275 0.026900 2.845775 1.442441 2.845775 \n", + "1 3.243124 0.061468 0.287511 0.116674 0.287511 \n", + "2 3.013205 0.022677 2.097526 1.261806 2.131399 \n", + "3 2.979140 0.028124 0.793993 0.523751 2.196469 \n", + "4 2.377142 0.021857 2.139993 1.304687 2.139993 \n", + ".. ... ... ... ... ... \n", + "212 10.539919 0.239889 1.336351 0.441290 1.336351 \n", + "213 8.561497 0.129386 0.956787 0.408402 0.966132 \n", + "214 6.157476 0.122835 1.745086 2.199006 2.262194 \n", + "215 3.790466 0.127067 1.332429 1.077809 1.332429 \n", + "216 2.594644 0.007079 0.369586 0.185078 0.375829 \n", + "\n", + " min_speed median_speed mean_speed \n", + "id \n", + "0 1.352343 1.978832 2.010321 \n", + "1 0.116674 0.184148 0.190783 \n", + "2 1.261806 1.945054 1.848956 \n", + "3 0.523751 1.697052 1.616889 \n", + "4 1.142313 1.321552 1.465801 \n", + ".. ... ... ... \n", + "212 0.389653 0.828371 0.804487 \n", + "213 0.170895 0.416961 0.540956 \n", + "214 1.745086 2.202081 2.125525 \n", + "215 1.077809 1.265536 1.242683 \n", + "216 0.183949 0.303257 0.291096 \n", + "\n", + "[217 rows x 13 columns]" + ] + }, + "execution_count": 15, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "mua_times = (MuaEventsV1 & selection_key).fetch1_dataframe()\n", + "mua_times" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "(1625935966.608866, 1625935994.6048138)" + ] + }, + "execution_count": 16, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "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iIiIiIiIsonBNyIiIiIiIiIiogxh8I0oQwwGA37wgx/AYDDkeleICgrPHaLk8fwhSg7PHaLk8fwhio0134iIiIiIiIiIiDKEmW9EREREREREREQZwuAbERERERERERFRhjD4RkRERERERERElCEMvhEREREREREREWUIg29EREREREREREQZwuAbERERERERERFRhjD4RkRERERERERElCEMvhEREREREREREWUIg29EREREREREREQZwuAbERERERERERFRhjD4RkRERERERERElCEMvhEREREREREREWUIg29EREREREREREQZwuAbERERERERERFRhjD4RkRERERERERElCEMvhEREREREREREWUIg29EREREREREREQZUvDBN6/Xi+9973uYMWMGjEYjZs6cidtvvx1+v1/aRhAEbNiwAa2trTAajVi5ciW2b9+ew70mIiIiIiIiIqJSUPDBt7vvvhuPPvooHnzwQezYsQP33HMP7r33XjzwwAPSNvfccw82bdqEBx98EO+++y6am5uxatUqjI2N5XDPiYiIiIiIiIio2KkEQRByvROpOPvss9HU1IRf/vKX0ufOP/98mEwmPPXUUxAEAa2trVi/fj2+/e1vAwBcLheamppw991346qrrsrVrhMRERERERERUZHT5noHUnXcccfh0Ucfxa5duzB37lx8+OGHeOutt3D//fcDANrb29Hb24vVq1dL32MwGHDiiSfi7bffjhh8c7lccLlc0sd+vx/Dw8Oor6+HSqXK6O9ERERERERERET5SxAEjI2NobW1FWp19IWlBR98+/a3vw2z2Yz58+dDo9HA5/PhzjvvxCWXXAIA6O3tBQA0NTUpvq+pqQkdHR0RX/euu+7CD3/4w8ztOBERERERERERFbTOzk5MmTIl6jYFH3x77rnn8PTTT+OZZ57BwoUL8cEHH2D9+vVobW3F5ZdfLm0XnK0mCELUDLZbb70VN9xwg/Sx2WzG1KlT0dnZiaqqqvT/IrGYzcD/+38TH194IVBdnf39SCfxdzIaAYNB+TWXC3A4iuP3zLVo7zPA95qISoP8WgjwukdE6Rc85uIYi4ioqFksFrS1taGysjLmtgUffLvppptwyy234Atf+AIAYPHixejo6MBdd92Fyy+/HM3NzQACGXAtLS3S9/X394dkw8kZDAYYwgQqqqqqchN8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", + "text/plain": [ + "
    " + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "import matplotlib.pyplot as plt\n", + "import numpy as np\n", + "\n", + "fig, axes = plt.subplots(2, 1, sharex=True, figsize=(15, 4))\n", + "axes[0].plot(\n", + " time,\n", + " multiunit_firing_rate,\n", + ")\n", + "axes[0].set_ylabel(\"firing rate (Hz)\")\n", + "axes[0].set_title(\"multiunit\")\n", + "axes[1].fill_between(\n", + " time, position_info[\"speed\"].iloc[time_ind_slice], color=\"lightgrey\"\n", + ")\n", + "axes[1].set_ylabel(\"speed (cm/s)\")\n", + "axes[1].set_xlabel(\"time (s)\")\n", + "\n", + "in_bounds = np.logical_and(\n", + " mua_times.start_time >= time[0], mua_times.end_time <= time[-1]\n", + ")\n", + "\n", + "for mua_time in mua_times.loc[in_bounds].itertuples():\n", + " axes[0].axvspan(\n", + " mua_time.start_time, mua_time.end_time, color=\"red\", alpha=0.3\n", + " )\n", + " axes[1].axvspan(\n", + " mua_time.start_time, mua_time.end_time, color=\"red\", alpha=0.3\n", + " )\n", + "axes[1].set_ylim((0, 80))\n", + "axes[1].axhline(4, color=\"black\", linestyle=\"--\")\n", + "axes[1].set_xlim((time[0], time[-1]))" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " Time intervals used for analysis\n", + "
    \n", + " \n", + " \n", + " \n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "
    \n", + "

    nwb_file_name

    \n", + " name of the NWB file\n", + "
    \n", + "

    interval_list_name

    \n", + " descriptive name of this interval list\n", + "
    \n", + "

    valid_times

    \n", + " numpy array with start/end times for each interval\n", + "
    \n", + "

    pipeline

    \n", + " type of interval list (e.g. 'position', 'spikesorting_recording_v1')\n", + "
    mediumnwb20230802_.nwb0e848c38-9105-4ea4-b6ba-dbdd5b46a088=BLOB=spikesorting_artifact_v1
    mediumnwb20230802_.nwb0f91197e-bebb-4dc6-ad41-5bf89c3eed28=BLOB=spikesorting_artifact_v1
    mediumnwb20230802_.nwb15c8a3e8-5ce9-4654-891e-6ee4109d6f1a=BLOB=spikesorting_artifact_v1
    mediumnwb20230802_.nwb2b93bcd0-7b05-457c-8aab-c41ef543ecf2=BLOB=spikesorting_artifact_v1
    mediumnwb20230802_.nwb2b9fbf14-74a0-4294-a805-26702340aac9=BLOB=spikesorting_artifact_v1
    mediumnwb20230802_.nwb3a34ab35-eca6-406b-abab-c866a9f41fb9=BLOB=spikesorting_artifact_v1
    mediumnwb20230802_.nwb3fecf0af-6ce7-474c-b933-9feb746993a0=BLOB=spikesorting_artifact_v1
    mediumnwb20230802_.nwb45f6b9a1-eef3-46eb-866d-d0999afebda6=BLOB=spikesorting_artifact_v1
    mediumnwb20230802_.nwb5c68f0f0-f577-4905-8a09-e4d171d0a22d=BLOB=spikesorting_artifact_v1
    mediumnwb20230802_.nwb686d9951-1c0f-4d5e-9f5c-09e6fd8bdd4c=BLOB=spikesorting_artifact_v1
    mediumnwb20230802_.nwb69f7d164-efc8-4621-b83c-77bc7459dbc2=BLOB=spikesorting_artifact_v1
    mediumnwb20230802_.nwb719e8a86-fcf1-4ffc-8c1f-ea912f67ad5d=BLOB=spikesorting_artifact_v1
    \n", + "

    ...

    \n", + "

    Total: 24

    \n", + " " + ], + "text/plain": [ + "*nwb_file_name *interval_list valid_time pipeline \n", + "+------------+ +------------+ +--------+ +------------+\n", + "mediumnwb20230 0e848c38-9105- =BLOB= spikesorting_a\n", + "mediumnwb20230 0f91197e-bebb- =BLOB= spikesorting_a\n", + "mediumnwb20230 15c8a3e8-5ce9- =BLOB= spikesorting_a\n", + "mediumnwb20230 2b93bcd0-7b05- =BLOB= spikesorting_a\n", + "mediumnwb20230 2b9fbf14-74a0- =BLOB= spikesorting_a\n", + "mediumnwb20230 3a34ab35-eca6- =BLOB= spikesorting_a\n", + "mediumnwb20230 3fecf0af-6ce7- =BLOB= spikesorting_a\n", + "mediumnwb20230 45f6b9a1-eef3- =BLOB= spikesorting_a\n", + "mediumnwb20230 5c68f0f0-f577- =BLOB= spikesorting_a\n", + "mediumnwb20230 686d9951-1c0f- =BLOB= spikesorting_a\n", + "mediumnwb20230 69f7d164-efc8- =BLOB= spikesorting_a\n", + "mediumnwb20230 719e8a86-fcf1- =BLOB= spikesorting_a\n", + " ...\n", + " (Total: 24)" + ] + }, + "execution_count": 17, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "from spyglass.common import IntervalList\n", + "\n", + "IntervalList() & {\"nwb_file_name\": nwb_copy_file_name, \"pipeline\": \"spikesorting_artifact_v1\"}" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + "
    \n", + " \n", + " \n", + " \n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "
    \n", + "

    artifact_param_name

    \n", + " \n", + "
    \n", + "

    recording_id

    \n", + " \n", + "
    \n", + "

    artifact_id

    \n", + " \n", + "
    \n", + "

    artifact_params

    \n", + " \n", + "
    \n", + "

    analysis_file_name

    \n", + " name of the file\n", + "
    \n", + "

    object_id

    \n", + " Object ID for the processed recording in NWB file\n", + "
    nonef1427e00-2974-4301-b2ac-b4dc29277c510e848c38-9105-4ea4-b6ba-dbdd5b46a088=BLOB=mediumnwb20230802_3BWJOEGAO1.nwb8366dcfd-bd90-470f-b08c-183bd44dcd1f
    none3c40ebdc-0b61-4105-9971-e1348bd49bc70f91197e-bebb-4dc6-ad41-5bf89c3eed28=BLOB=mediumnwb20230802_85VG1GLTSR.nwb2d6e841c-4f98-42b7-9cbf-097fa8ba0766
    none1e3f3707-613e-4a44-93f1-c7e5484112cd15c8a3e8-5ce9-4654-891e-6ee4109d6f1a=BLOB=mediumnwb20230802_H70AAE9UEI.nwb34550b0b-36c7-4dfb-b1ba-900fc9247da8
    none72f70c5a-bc0f-46cb-b22f-33bafe2315df2b93bcd0-7b05-457c-8aab-c41ef543ecf2=BLOB=mediumnwb20230802_OFQSUAGB74.nwb3a1b3df6-fa85-4006-ab9b-4bff45680516
    none3a2c3eed-413a-452a-83c8-0e4648141bde2b9fbf14-74a0-4294-a805-26702340aac9=BLOB=mediumnwb20230802_G0STLTBOSC.nwbec5170e0-277a-4626-9120-b24574eae650
    noned14ae25a-2796-4203-ba0b-f28768536cbe3a34ab35-eca6-406b-abab-c866a9f41fb9=BLOB=mediumnwb20230802_IG73IGEYPA.nwba3406f7e-1137-4c34-8715-e0323d074153
    none76ee4ab3-da3e-4a68-9159-635fbf5f8a043fecf0af-6ce7-474c-b933-9feb746993a0=BLOB=mediumnwb20230802_LFO7YW7IIA.nwbcfe309be-3748-4dc8-9c71-81bd5c1067b7
    none449b64e3-db0b-437e-a1b9-0d29928aa2dd45f6b9a1-eef3-46eb-866d-d0999afebda6=BLOB=mediumnwb20230802_R19M5A499A.nwb68db8ac5-d008-4720-a3f8-162b0671313d
    nonef07bc0b0-de6b-4424-8ef9-766213aaca265c68f0f0-f577-4905-8a09-e4d171d0a22d=BLOB=mediumnwb20230802_GF6Z0P5KYV.nwb80c14292-a179-4c0f-9ff9-79016038ce95
    none328da21c-1d9c-41e2-9800-76b3484b707b686d9951-1c0f-4d5e-9f5c-09e6fd8bdd4c=BLOB=mediumnwb20230802_YSZXPEGP4X.nwb623a46f8-be44-434b-8aee-49155070f3f7
    noneb81f1ed9-fb2e-4f5c-93d8-d9cc0f11887569f7d164-efc8-4621-b83c-77bc7459dbc2=BLOB=mediumnwb20230802_QBQBH0I2OO.nwb101d753a-72fb-47a4-8734-962f8ef4f477
    noneaff78f2f-2ba0-412a-95cc-447c3a2f4683719e8a86-fcf1-4ffc-8c1f-ea912f67ad5d=BLOB=mediumnwb20230802_42H3PR863Y.nwb6c5f3cd0-903a-42b5-ad68-261789bfd1a8
    \n", + "

    ...

    \n", + "

    Total: 24

    \n", + " " + ], + "text/plain": [ + "*artifact_para *recording_id *artifact_id artifact_p analysis_file_ object_id \n", + "+------------+ +------------+ +------------+ +--------+ +------------+ +------------+\n", + "none f1427e00-2974- 0e848c38-9105- =BLOB= mediumnwb20230 8366dcfd-bd90-\n", + "none 3c40ebdc-0b61- 0f91197e-bebb- =BLOB= mediumnwb20230 2d6e841c-4f98-\n", + "none 1e3f3707-613e- 15c8a3e8-5ce9- =BLOB= mediumnwb20230 34550b0b-36c7-\n", + "none 72f70c5a-bc0f- 2b93bcd0-7b05- =BLOB= mediumnwb20230 3a1b3df6-fa85-\n", + "none 3a2c3eed-413a- 2b9fbf14-74a0- =BLOB= mediumnwb20230 ec5170e0-277a-\n", + "none d14ae25a-2796- 3a34ab35-eca6- =BLOB= mediumnwb20230 a3406f7e-1137-\n", + "none 76ee4ab3-da3e- 3fecf0af-6ce7- =BLOB= mediumnwb20230 cfe309be-3748-\n", + "none 449b64e3-db0b- 45f6b9a1-eef3- =BLOB= mediumnwb20230 68db8ac5-d008-\n", + "none f07bc0b0-de6b- 5c68f0f0-f577- =BLOB= mediumnwb20230 80c14292-a179-\n", + "none 328da21c-1d9c- 686d9951-1c0f- =BLOB= mediumnwb20230 623a46f8-be44-\n", + "none b81f1ed9-fb2e- 69f7d164-efc8- =BLOB= mediumnwb20230 101d753a-72fb-\n", + "none aff78f2f-2ba0- 719e8a86-fcf1- =BLOB= mediumnwb20230 6c5f3cd0-903a-\n", + " ...\n", + " (Total: 24)" + ] + }, + "execution_count": 18, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "(sgs.ArtifactDetectionParameters\n", + "* sgs.SpikeSortingRecording\n", + "* sgs.ArtifactDetectionSelection)" + ] + }, + { + "cell_type": "code", + "execution_count": 29, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + "
    \n", + " \n", + " \n", + " \n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "
    \n", + "

    merge_id

    \n", + " \n", + "
    \n", + "

    artifact_param_name

    \n", + " \n", + "
    \n", + "

    recording_id

    \n", + " \n", + "
    \n", + "

    artifact_id

    \n", + " \n", + "
    \n", + "

    sorting_id

    \n", + " \n", + "
    \n", + "

    curation_id

    \n", + " \n", + "
    \n", + "

    artifact_params

    \n", + " \n", + "
    \n", + "

    analysis_file_name

    \n", + " name of the file\n", + "
    \n", + "

    object_id

    \n", + " Object ID for the processed recording in NWB file\n", + "
    485a4ddf-332d-35b5-3ad4-0561736c1844nonef15351b3-d8e9-49a1-a306-4f366f1ee535a5470cef-fc31-4723-9e1b-a024e73ef3b108a302b6-5505-40fa-b4d5-62162f8eef580=BLOB=mediumnwb20230802_JVBY43AQFF.nwbf639dd9a-fc4f-483e-a9c5-f487ecd11292
    485a4ddf-332d-35b5-3ad4-0561736c1844nonef1427e00-2974-4301-b2ac-b4dc29277c510e848c38-9105-4ea4-b6ba-dbdd5b46a08808a302b6-5505-40fa-b4d5-62162f8eef580=BLOB=mediumnwb20230802_3BWJOEGAO1.nwb8366dcfd-bd90-470f-b08c-183bd44dcd1f
    485a4ddf-332d-35b5-3ad4-0561736c1844nonef07bc0b0-de6b-4424-8ef9-766213aaca265c68f0f0-f577-4905-8a09-e4d171d0a22d08a302b6-5505-40fa-b4d5-62162f8eef580=BLOB=mediumnwb20230802_GF6Z0P5KYV.nwb80c14292-a179-4c0f-9ff9-79016038ce95
    485a4ddf-332d-35b5-3ad4-0561736c1844nonee59e77e9-dd41-4f58-a75b-17271b78c0d88cc7a814-8e4a-4b87-ae71-80ca1f5771b108a302b6-5505-40fa-b4d5-62162f8eef580=BLOB=mediumnwb20230802_8SB3X7Y9YA.nwbc880110b-1dbf-4cc1-99ff-3766ade81fed
    485a4ddf-332d-35b5-3ad4-0561736c1844noned14ae25a-2796-4203-ba0b-f28768536cbe3a34ab35-eca6-406b-abab-c866a9f41fb908a302b6-5505-40fa-b4d5-62162f8eef580=BLOB=mediumnwb20230802_IG73IGEYPA.nwba3406f7e-1137-4c34-8715-e0323d074153
    485a4ddf-332d-35b5-3ad4-0561736c1844noneb81f1ed9-fb2e-4f5c-93d8-d9cc0f11887569f7d164-efc8-4621-b83c-77bc7459dbc208a302b6-5505-40fa-b4d5-62162f8eef580=BLOB=mediumnwb20230802_QBQBH0I2OO.nwb101d753a-72fb-47a4-8734-962f8ef4f477
    485a4ddf-332d-35b5-3ad4-0561736c1844noneaff78f2f-2ba0-412a-95cc-447c3a2f4683719e8a86-fcf1-4ffc-8c1f-ea912f67ad5d08a302b6-5505-40fa-b4d5-62162f8eef580=BLOB=mediumnwb20230802_42H3PR863Y.nwb6c5f3cd0-903a-42b5-ad68-261789bfd1a8
    485a4ddf-332d-35b5-3ad4-0561736c1844nonea9b7cec0-1256-49cf-abf0-8c45fd15537974270cba-36ee-4afb-ab50-2a6cc948e68c08a302b6-5505-40fa-b4d5-62162f8eef580=BLOB=mediumnwb20230802_5GUFKQ59T6.nwb498d52a8-47d1-41c2-bd45-2ac796fce4cd
    485a4ddf-332d-35b5-3ad4-0561736c1844nonea3f5b9e7-7c79-4eb4-b5ed-910191c615c2f9cc9158-bea2-4de2-811d-1fb895c048a908a302b6-5505-40fa-b4d5-62162f8eef580=BLOB=mediumnwb20230802_OQZ8C41NHS.nwbd49e9245-149c-4725-bd0f-d69b78e0a33a
    485a4ddf-332d-35b5-3ad4-0561736c1844none9e332d82-1daf-4e92-bb50-12e4f94308759ed11db5-c42e-491a-8caf-7d9a37a65f1308a302b6-5505-40fa-b4d5-62162f8eef580=BLOB=mediumnwb20230802_30PFKCH9HH.nwba45a4c86-d748-48f8-b406-4da381a74737
    485a4ddf-332d-35b5-3ad4-0561736c1844none7f128981-6868-4976-ba20-248655dcac21f4b9301f-bc91-455b-9474-c801093f385608a302b6-5505-40fa-b4d5-62162f8eef580=BLOB=mediumnwb20230802_F9B938GB2N.nwbb06a3ec5-17a2-49a3-bd7f-475cb07081a0
    485a4ddf-332d-35b5-3ad4-0561736c1844none7cc37209-7c28-443d-8f65-d8b01ca49a9af8650c19-8964-44ea-bd87-0245f1d2f93408a302b6-5505-40fa-b4d5-62162f8eef580=BLOB=mediumnwb20230802_XAQMO7WRC5.nwb38522acb-ba02-4fe1-b715-3c7485cca749
    \n", + "

    ...

    \n", + "

    Total: 552

    \n", + " " + ], + "text/plain": [ + "*merge_id *artifact_para *recording_id *artifact_id sorting_id curation_id artifact_p analysis_file_ object_id \n", + "+------------+ +------------+ +------------+ +------------+ +------------+ +------------+ +--------+ +------------+ +------------+\n", + "485a4ddf-332d- none f15351b3-d8e9- a5470cef-fc31- 08a302b6-5505- 0 =BLOB= mediumnwb20230 f639dd9a-fc4f-\n", + "485a4ddf-332d- none f1427e00-2974- 0e848c38-9105- 08a302b6-5505- 0 =BLOB= mediumnwb20230 8366dcfd-bd90-\n", + "485a4ddf-332d- none f07bc0b0-de6b- 5c68f0f0-f577- 08a302b6-5505- 0 =BLOB= mediumnwb20230 80c14292-a179-\n", + "485a4ddf-332d- none e59e77e9-dd41- 8cc7a814-8e4a- 08a302b6-5505- 0 =BLOB= mediumnwb20230 c880110b-1dbf-\n", + "485a4ddf-332d- none d14ae25a-2796- 3a34ab35-eca6- 08a302b6-5505- 0 =BLOB= mediumnwb20230 a3406f7e-1137-\n", + "485a4ddf-332d- none b81f1ed9-fb2e- 69f7d164-efc8- 08a302b6-5505- 0 =BLOB= mediumnwb20230 101d753a-72fb-\n", + "485a4ddf-332d- none aff78f2f-2ba0- 719e8a86-fcf1- 08a302b6-5505- 0 =BLOB= mediumnwb20230 6c5f3cd0-903a-\n", + "485a4ddf-332d- none a9b7cec0-1256- 74270cba-36ee- 08a302b6-5505- 0 =BLOB= mediumnwb20230 498d52a8-47d1-\n", + "485a4ddf-332d- none a3f5b9e7-7c79- f9cc9158-bea2- 08a302b6-5505- 0 =BLOB= mediumnwb20230 d49e9245-149c-\n", + "485a4ddf-332d- none 9e332d82-1daf- 9ed11db5-c42e- 08a302b6-5505- 0 =BLOB= mediumnwb20230 a45a4c86-d748-\n", + "485a4ddf-332d- none 7f128981-6868- f4b9301f-bc91- 08a302b6-5505- 0 =BLOB= mediumnwb20230 b06a3ec5-17a2-\n", + "485a4ddf-332d- none 7cc37209-7c28- f8650c19-8964- 08a302b6-5505- 0 =BLOB= mediumnwb20230 38522acb-ba02-\n", + " ...\n", + " (Total: 552)" + ] + }, + "execution_count": 29, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "SpikeSortingOutput.CurationV1() * (\n", + " sgs.ArtifactDetectionParameters\n", + " * sgs.SpikeSortingRecording\n", + " * sgs.ArtifactDetectionSelection\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "(\n", + " IntervalList()\n", + " & {\n", + " \"nwb_file_name\": nwb_copy_file_name,\n", + " \"pipeline\": \"spikesorting_artifact_v1\",\n", + " }\n", + ").proj(artifact_id=\"interval_list_name\")" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + "
    \n", + " \n", + " \n", + " \n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "
    \n", + "

    recording_id

    \n", + " \n", + "
    \n", + "

    artifact_id

    \n", + " \n", + "
    \n", + "

    analysis_file_name

    \n", + " name of the file\n", + "
    \n", + "

    object_id

    \n", + " Object ID for the processed recording in NWB file\n", + "
    \n", + "

    artifact_param_name

    \n", + " \n", + "
    04f3ecb4-a18c-4ffb-85d8-2f5f62d4d6d47a93bd27-5108-4290-89a2-2f8770664b35mediumnwb20230802_F7HG9E9J3I.nwb16bded49-3fc2-4e37-9ac6-385eec091740none
    1d2b5966-415a-4c65-955a-0e422d8b5b00e4921df8-99b5-4f52-b3c2-988b9433e0cfmediumnwb20230802_C0I26JVUNV.nwba07a4fcc-ac84-4d07-a036-b32c7e2ceb28none
    1e3f3707-613e-4a44-93f1-c7e5484112cd15c8a3e8-5ce9-4654-891e-6ee4109d6f1amediumnwb20230802_H70AAE9UEI.nwb34550b0b-36c7-4dfb-b1ba-900fc9247da8none
    2402805a-04f9-4a88-9ccf-071376c8de19d581b117-160e-4311-b096-7781a4de4394mediumnwb20230802_5MEOIHZ5E5.nwbbf877f6e-5daf-4d70-ab23-fc2b7c132370none
    24107d8c-ce26-4c77-8f6a-bf6955d8a3c7d1925dc7-e3b0-47ef-adbc-1af129b67048mediumnwb20230802_MKQ2TG5YZC.nwb7f55e942-7563-466a-ba56-b82ea5089be4none
    257c077b-8f3b-4abb-a631-6b8084d6a1eae289e03d-32ad-461a-a1cc-c88537343149mediumnwb20230802_C2DEV7V2C6.nwbc19ca39e-50a4-4e87-a8e7-22ccf5979f27none
    328da21c-1d9c-41e2-9800-76b3484b707b686d9951-1c0f-4d5e-9f5c-09e6fd8bdd4cmediumnwb20230802_YSZXPEGP4X.nwb623a46f8-be44-434b-8aee-49155070f3f7none
    3a2c3eed-413a-452a-83c8-0e4648141bde2b9fbf14-74a0-4294-a805-26702340aac9mediumnwb20230802_G0STLTBOSC.nwbec5170e0-277a-4626-9120-b24574eae650none
    3c40ebdc-0b61-4105-9971-e1348bd49bc70f91197e-bebb-4dc6-ad41-5bf89c3eed28mediumnwb20230802_85VG1GLTSR.nwb2d6e841c-4f98-42b7-9cbf-097fa8ba0766none
    449b64e3-db0b-437e-a1b9-0d29928aa2dd45f6b9a1-eef3-46eb-866d-d0999afebda6mediumnwb20230802_R19M5A499A.nwb68db8ac5-d008-4720-a3f8-162b0671313dnone
    72f70c5a-bc0f-46cb-b22f-33bafe2315df2b93bcd0-7b05-457c-8aab-c41ef543ecf2mediumnwb20230802_OFQSUAGB74.nwb3a1b3df6-fa85-4006-ab9b-4bff45680516none
    76ee4ab3-da3e-4a68-9159-635fbf5f8a043fecf0af-6ce7-474c-b933-9feb746993a0mediumnwb20230802_LFO7YW7IIA.nwbcfe309be-3748-4dc8-9c71-81bd5c1067b7none
    \n", + "

    ...

    \n", + "

    Total: 24

    \n", + " " + ], + "text/plain": [ + "*recording_id *artifact_id analysis_file_ object_id artifact_param\n", + "+------------+ +------------+ +------------+ +------------+ +------------+\n", + "04f3ecb4-a18c- 7a93bd27-5108- mediumnwb20230 16bded49-3fc2- none \n", + "1d2b5966-415a- e4921df8-99b5- mediumnwb20230 a07a4fcc-ac84- none \n", + "1e3f3707-613e- 15c8a3e8-5ce9- mediumnwb20230 34550b0b-36c7- none \n", + "2402805a-04f9- d581b117-160e- mediumnwb20230 bf877f6e-5daf- none \n", + "24107d8c-ce26- d1925dc7-e3b0- mediumnwb20230 7f55e942-7563- none \n", + "257c077b-8f3b- e289e03d-32ad- mediumnwb20230 c19ca39e-50a4- none \n", + "328da21c-1d9c- 686d9951-1c0f- mediumnwb20230 623a46f8-be44- none \n", + "3a2c3eed-413a- 2b9fbf14-74a0- mediumnwb20230 ec5170e0-277a- none \n", + "3c40ebdc-0b61- 0f91197e-bebb- mediumnwb20230 2d6e841c-4f98- none \n", + "449b64e3-db0b- 45f6b9a1-eef3- mediumnwb20230 68db8ac5-d008- none \n", + "72f70c5a-bc0f- 2b93bcd0-7b05- mediumnwb20230 3a1b3df6-fa85- none \n", + "76ee4ab3-da3e- 3fecf0af-6ce7- mediumnwb20230 cfe309be-3748- none \n", + " ...\n", + " (Total: 24)" + ] + }, + "execution_count": 20, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "sgs.SpikeSortingRecording() * sgs.ArtifactDetectionSelection()" + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + "
    \n", + " \n", + " \n", + " \n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "
    \n", + "

    merge_id

    \n", + " \n", + "
    \n", + "

    recording_id

    \n", + " \n", + "
    \n", + "

    sorting_id

    \n", + " \n", + "
    \n", + "

    curation_id

    \n", + " \n", + "
    \n", + "

    analysis_file_name

    \n", + " name of the file\n", + "
    \n", + "

    object_id

    \n", + " Object ID for the processed recording in NWB file\n", + "
    485a4ddf-332d-35b5-3ad4-0561736c1844f15351b3-d8e9-49a1-a306-4f366f1ee53508a302b6-5505-40fa-b4d5-62162f8eef580mediumnwb20230802_JVBY43AQFF.nwbf639dd9a-fc4f-483e-a9c5-f487ecd11292
    485a4ddf-332d-35b5-3ad4-0561736c1844f1427e00-2974-4301-b2ac-b4dc29277c5108a302b6-5505-40fa-b4d5-62162f8eef580mediumnwb20230802_3BWJOEGAO1.nwb8366dcfd-bd90-470f-b08c-183bd44dcd1f
    485a4ddf-332d-35b5-3ad4-0561736c1844f07bc0b0-de6b-4424-8ef9-766213aaca2608a302b6-5505-40fa-b4d5-62162f8eef580mediumnwb20230802_GF6Z0P5KYV.nwb80c14292-a179-4c0f-9ff9-79016038ce95
    485a4ddf-332d-35b5-3ad4-0561736c1844e59e77e9-dd41-4f58-a75b-17271b78c0d808a302b6-5505-40fa-b4d5-62162f8eef580mediumnwb20230802_8SB3X7Y9YA.nwbc880110b-1dbf-4cc1-99ff-3766ade81fed
    485a4ddf-332d-35b5-3ad4-0561736c1844d14ae25a-2796-4203-ba0b-f28768536cbe08a302b6-5505-40fa-b4d5-62162f8eef580mediumnwb20230802_IG73IGEYPA.nwba3406f7e-1137-4c34-8715-e0323d074153
    485a4ddf-332d-35b5-3ad4-0561736c1844b81f1ed9-fb2e-4f5c-93d8-d9cc0f11887508a302b6-5505-40fa-b4d5-62162f8eef580mediumnwb20230802_QBQBH0I2OO.nwb101d753a-72fb-47a4-8734-962f8ef4f477
    485a4ddf-332d-35b5-3ad4-0561736c1844aff78f2f-2ba0-412a-95cc-447c3a2f468308a302b6-5505-40fa-b4d5-62162f8eef580mediumnwb20230802_42H3PR863Y.nwb6c5f3cd0-903a-42b5-ad68-261789bfd1a8
    485a4ddf-332d-35b5-3ad4-0561736c1844a9b7cec0-1256-49cf-abf0-8c45fd15537908a302b6-5505-40fa-b4d5-62162f8eef580mediumnwb20230802_5GUFKQ59T6.nwb498d52a8-47d1-41c2-bd45-2ac796fce4cd
    485a4ddf-332d-35b5-3ad4-0561736c1844a3f5b9e7-7c79-4eb4-b5ed-910191c615c208a302b6-5505-40fa-b4d5-62162f8eef580mediumnwb20230802_OQZ8C41NHS.nwbd49e9245-149c-4725-bd0f-d69b78e0a33a
    485a4ddf-332d-35b5-3ad4-0561736c18449e332d82-1daf-4e92-bb50-12e4f943087508a302b6-5505-40fa-b4d5-62162f8eef580mediumnwb20230802_30PFKCH9HH.nwba45a4c86-d748-48f8-b406-4da381a74737
    485a4ddf-332d-35b5-3ad4-0561736c18447f128981-6868-4976-ba20-248655dcac2108a302b6-5505-40fa-b4d5-62162f8eef580mediumnwb20230802_F9B938GB2N.nwbb06a3ec5-17a2-49a3-bd7f-475cb07081a0
    485a4ddf-332d-35b5-3ad4-0561736c18447cc37209-7c28-443d-8f65-d8b01ca49a9a08a302b6-5505-40fa-b4d5-62162f8eef580mediumnwb20230802_XAQMO7WRC5.nwb38522acb-ba02-4fe1-b715-3c7485cca749
    \n", + "

    ...

    \n", + "

    Total: 552

    \n", + " " + ], + "text/plain": [ + "*merge_id *recording_id sorting_id curation_id analysis_file_ object_id \n", + "+------------+ +------------+ +------------+ +------------+ +------------+ +------------+\n", + "485a4ddf-332d- f15351b3-d8e9- 08a302b6-5505- 0 mediumnwb20230 f639dd9a-fc4f-\n", + "485a4ddf-332d- f1427e00-2974- 08a302b6-5505- 0 mediumnwb20230 8366dcfd-bd90-\n", + "485a4ddf-332d- f07bc0b0-de6b- 08a302b6-5505- 0 mediumnwb20230 80c14292-a179-\n", + "485a4ddf-332d- e59e77e9-dd41- 08a302b6-5505- 0 mediumnwb20230 c880110b-1dbf-\n", + "485a4ddf-332d- d14ae25a-2796- 08a302b6-5505- 0 mediumnwb20230 a3406f7e-1137-\n", + "485a4ddf-332d- b81f1ed9-fb2e- 08a302b6-5505- 0 mediumnwb20230 101d753a-72fb-\n", + "485a4ddf-332d- aff78f2f-2ba0- 08a302b6-5505- 0 mediumnwb20230 6c5f3cd0-903a-\n", + "485a4ddf-332d- a9b7cec0-1256- 08a302b6-5505- 0 mediumnwb20230 498d52a8-47d1-\n", + "485a4ddf-332d- a3f5b9e7-7c79- 08a302b6-5505- 0 mediumnwb20230 d49e9245-149c-\n", + "485a4ddf-332d- 9e332d82-1daf- 08a302b6-5505- 0 mediumnwb20230 a45a4c86-d748-\n", + "485a4ddf-332d- 7f128981-6868- 08a302b6-5505- 0 mediumnwb20230 b06a3ec5-17a2-\n", + "485a4ddf-332d- 7cc37209-7c28- 08a302b6-5505- 0 mediumnwb20230 38522acb-ba02-\n", + " ...\n", + " (Total: 552)" + ] + }, + "execution_count": 21, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "SpikeSortingOutput.CurationV1() * sgs.SpikeSortingRecording()" + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "metadata": {}, + "outputs": [ + { + "ename": "DuplicateError", + "evalue": "(\"Duplicate entry 'mediumnwb20230802_.nwb-test_artifact_times' for key 'interval_list.PRIMARY'\", 'To ignore duplicate entries in insert, set skip_duplicates=True')", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mDuplicateError\u001b[0m Traceback (most recent call last)", + "Cell \u001b[0;32mIn[22], line 1\u001b[0m\n\u001b[0;32m----> 1\u001b[0m \u001b[43mIntervalList\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43minsert1\u001b[49m\u001b[43m(\u001b[49m\u001b[43m{\u001b[49m\n\u001b[1;32m 2\u001b[0m \u001b[43m \u001b[49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mnwb_file_name\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[43m:\u001b[49m\u001b[43m \u001b[49m\u001b[43mnwb_copy_file_name\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 3\u001b[0m \u001b[43m \u001b[49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43minterval_list_name\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[43m:\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mtest_artifact_times\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[43m,\u001b[49m\n\u001b[1;32m 4\u001b[0m \u001b[43m \u001b[49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mvalid_times\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[43m:\u001b[49m\u001b[43m \u001b[49m\u001b[43m[\u001b[49m\u001b[43m]\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 5\u001b[0m \u001b[43m}\u001b[49m\u001b[43m)\u001b[49m\n", + "File \u001b[0;32m~/miniconda3/envs/spyglass/lib/python3.9/site-packages/datajoint/table.py:337\u001b[0m, in \u001b[0;36mTable.insert1\u001b[0;34m(self, row, **kwargs)\u001b[0m\n\u001b[1;32m 330\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21minsert1\u001b[39m(\u001b[38;5;28mself\u001b[39m, row, \u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39mkwargs):\n\u001b[1;32m 331\u001b[0m \u001b[38;5;250m \u001b[39m\u001b[38;5;124;03m\"\"\"\u001b[39;00m\n\u001b[1;32m 332\u001b[0m \u001b[38;5;124;03m Insert one data record into the table. For ``kwargs``, see ``insert()``.\u001b[39;00m\n\u001b[1;32m 333\u001b[0m \n\u001b[1;32m 334\u001b[0m \u001b[38;5;124;03m :param row: a numpy record, a dict-like object, or an ordered sequence to be inserted\u001b[39;00m\n\u001b[1;32m 335\u001b[0m \u001b[38;5;124;03m as one row.\u001b[39;00m\n\u001b[1;32m 336\u001b[0m \u001b[38;5;124;03m \"\"\"\u001b[39;00m\n\u001b[0;32m--> 337\u001b[0m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43minsert\u001b[49m\u001b[43m(\u001b[49m\u001b[43m(\u001b[49m\u001b[43mrow\u001b[49m\u001b[43m,\u001b[49m\u001b[43m)\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43mkwargs\u001b[49m\u001b[43m)\u001b[49m\n", + "File \u001b[0;32m~/miniconda3/envs/spyglass/lib/python3.9/site-packages/datajoint/table.py:453\u001b[0m, in \u001b[0;36mTable.insert\u001b[0;34m(self, rows, replace, skip_duplicates, ignore_extra_fields, allow_direct_insert)\u001b[0m\n\u001b[1;32m 449\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m err\u001b[38;5;241m.\u001b[39msuggest(\n\u001b[1;32m 450\u001b[0m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mTo ignore extra fields in insert, set ignore_extra_fields=True\u001b[39m\u001b[38;5;124m\"\u001b[39m\n\u001b[1;32m 451\u001b[0m )\n\u001b[1;32m 452\u001b[0m \u001b[38;5;28;01mexcept\u001b[39;00m DuplicateError \u001b[38;5;28;01mas\u001b[39;00m err:\n\u001b[0;32m--> 453\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m err\u001b[38;5;241m.\u001b[39msuggest(\n\u001b[1;32m 454\u001b[0m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mTo ignore duplicate entries in insert, set skip_duplicates=True\u001b[39m\u001b[38;5;124m\"\u001b[39m\n\u001b[1;32m 455\u001b[0m )\n", + "\u001b[0;31mDuplicateError\u001b[0m: (\"Duplicate entry 'mediumnwb20230802_.nwb-test_artifact_times' for key 'interval_list.PRIMARY'\", 'To ignore duplicate entries in insert, set skip_duplicates=True')" + ] + } + ], + "source": [ + "IntervalList.insert1({\n", + " \"nwb_file_name\": nwb_copy_file_name,\n", + " \"interval_list_name\": \"test_artifact_times\",\n", + " \"valid_times\": [],\n", + "})" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "spyglass", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.18" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/notebooks/py_scripts/10_Spike_SortingV0.py b/notebooks/py_scripts/10_Spike_SortingV0.py index 52971f7de..6daa28200 100644 --- a/notebooks/py_scripts/10_Spike_SortingV0.py +++ b/notebooks/py_scripts/10_Spike_SortingV0.py @@ -69,7 +69,7 @@ dj.config.load("dj_local_conf.json") # load config for database connection info import spyglass.common as sgc -import spyglass.spikesorting as sgs +import spyglass.spikesorting.v0 as sgs # ignore datajoint+jupyter async warnings import warnings @@ -84,15 +84,24 @@ # If you haven't already done so, add yourself to `LabTeam` # -name, email, dj_user = "Firstname Lastname", "example@gmail.com", "user" +# Full name, Google email address, DataJoint username, admin +name, email, dj_user, admin = ( + "Firstname Lastname", + "example@gmail.com", + "user", + 0, +) sgc.LabMember.insert_from_name(name) sgc.LabMember.LabMemberInfo.insert1( - [name, email, dj_user], skip_duplicates=True -) -sgc.LabTeam.LabTeamMember.insert1( - {"team_name": "My Team", "lab_member_name": name}, + [ + name, + email, + dj_user, + admin, + ], skip_duplicates=True, ) +sgc.LabMember.LabMemberInfo() # We can try `fetch` to confirm. # diff --git a/notebooks/py_scripts/10_Spike_SortingV1.py b/notebooks/py_scripts/10_Spike_SortingV1.py index cddda32d3..ae6c6fb82 100644 --- a/notebooks/py_scripts/10_Spike_SortingV1.py +++ b/notebooks/py_scripts/10_Spike_SortingV1.py @@ -261,7 +261,7 @@ # We now insert the curated spike sorting to a `Merge` table for feeding into downstream processing pipelines. # -from spyglass.spikesorting.merge import SpikeSortingOutput +from spyglass.spikesorting.spikesorting_merge import SpikeSortingOutput SpikeSortingOutput() diff --git a/notebooks/py_scripts/11_Curation.py b/notebooks/py_scripts/11_CurationV0.py similarity index 98% rename from notebooks/py_scripts/11_Curation.py rename to notebooks/py_scripts/11_CurationV0.py index 25eb698ad..f728512a2 100644 --- a/notebooks/py_scripts/11_Curation.py +++ b/notebooks/py_scripts/11_CurationV0.py @@ -47,7 +47,7 @@ os.chdir("..") dj.config.load("dj_local_conf.json") # load config for database connection info -from spyglass.spikesorting import SpikeSorting +from spyglass.spikesorting.v0 import SpikeSorting # - diff --git a/notebooks/py_scripts/24_Linearization.py b/notebooks/py_scripts/24_Linearization.py index 5ed9ecb89..90ec20eae 100644 --- a/notebooks/py_scripts/24_Linearization.py +++ b/notebooks/py_scripts/24_Linearization.py @@ -5,7 +5,7 @@ # extension: .py # format_name: light # format_version: '1.5' -# jupytext_version: 1.15.2 +# jupytext_version: 1.16.0 # kernelspec: # display_name: spyglass # language: python diff --git a/notebooks/py_scripts/32_Ripple_Detection.py b/notebooks/py_scripts/32_Ripple_Detection.py index 652795939..6e994bf30 100644 --- a/notebooks/py_scripts/32_Ripple_Detection.py +++ b/notebooks/py_scripts/32_Ripple_Detection.py @@ -5,7 +5,7 @@ # extension: .py # format_name: light # format_version: '1.5' -# jupytext_version: 1.15.2 +# jupytext_version: 1.16.0 # kernelspec: # display_name: spyglass # language: python diff --git a/notebooks/py_scripts/41_Extracting_Clusterless_Waveform_Features.py b/notebooks/py_scripts/41_Extracting_Clusterless_Waveform_Features.py index 232be4174..3880f94c4 100644 --- a/notebooks/py_scripts/41_Extracting_Clusterless_Waveform_Features.py +++ b/notebooks/py_scripts/41_Extracting_Clusterless_Waveform_Features.py @@ -146,7 +146,7 @@ # For clusterless decoding we do not need any manual curation, but for the sake of the pipeline, we need to store the output of the thresholding in the `CurationV1` table and insert this into the `SpikeSortingOutput` table. # + -from spyglass.spikesorting.merge import SpikeSortingOutput +from spyglass.spikesorting.spikesorting_merge import SpikeSortingOutput sorting_ids = ( sgs.SpikeSortingSelection & {"nwb_file_name": nwb_copy_file_name} @@ -155,7 +155,7 @@ for sorting_id in sorting_ids: try: sgs.CurationV1.insert_curation(sorting_id=sorting_id) - except KeyError: + except KeyError as e: pass SpikeSortingOutput.insert( @@ -250,7 +250,7 @@ # First we find the units we need: # + -from spyglass.spikesorting.merge import SpikeSortingOutput +from spyglass.spikesorting.spikesorting_merge import SpikeSortingOutput merge_ids = ( (SpikeSortingOutput.CurationV1 * sgs.SpikeSortingSelection) diff --git a/notebooks/py_scripts/42_Decoding_Clusterless.py b/notebooks/py_scripts/42_Decoding_Clusterless.py index 309747931..ce0dc9e88 100644 --- a/notebooks/py_scripts/42_Decoding_Clusterless.py +++ b/notebooks/py_scripts/42_Decoding_Clusterless.py @@ -53,7 +53,7 @@ ) # load config for database connection info # + -from spyglass.spikesorting.merge import SpikeSortingOutput +from spyglass.spikesorting.spikesorting_merge import SpikeSortingOutput import spyglass.spikesorting.v1 as sgs from spyglass.decoding.v1.waveform_features import UnitWaveformFeaturesSelection @@ -125,8 +125,39 @@ # + from spyglass.position import PositionOutput +import spyglass.position as sgp -PositionOutput.TrodesPosV1 & {"nwb_file_name": nwb_copy_file_name} + +sgp.v1.TrodesPosParams.insert1( + { + "trodes_pos_params_name": "default_decoding", + "params": { + "max_LED_separation": 9.0, + "max_plausible_speed": 300.0, + "position_smoothing_duration": 0.125, + "speed_smoothing_std_dev": 0.100, + "orient_smoothing_std_dev": 0.001, + "led1_is_front": 1, + "is_upsampled": 1, + "upsampling_sampling_rate": 250, + "upsampling_interpolation_method": "linear", + }, + }, + skip_duplicates=True, +) + +trodes_s_key = { + "nwb_file_name": nwb_copy_file_name, + "interval_list_name": "pos 0 valid times", + "trodes_pos_params_name": "default_decoding", +} +sgp.v1.TrodesPosSelection.insert1( + trodes_s_key, + skip_duplicates=True, +) +sgp.v1.TrodesPosV1.populate(trodes_s_key) + +PositionOutput.TrodesPosV1 & trodes_s_key # + from spyglass.decoding.v1.core import PositionGroup @@ -136,7 +167,7 @@ & { "nwb_file_name": nwb_copy_file_name, "interval_list_name": "pos 0 valid times", - "trodes_pos_params_name": "default", + "trodes_pos_params_name": "default_decoding", } ).fetch("merge_id") @@ -323,7 +354,7 @@ # We can load the results of the decoding: -decoding_results = (ClusterlessDecodingV1 & selection_key).load_results() +decoding_results = (ClusterlessDecodingV1 & selection_key).fetch_results() decoding_results # Finally, if we deleted the results, we can use the `cleanup` function to delete the results from the file system: @@ -349,12 +380,12 @@ # ( # position_info, # position_variable_names, -# ) = ClusterlessDecodingV1.load_position_info(selection_key) +# ) = ClusterlessDecodingV1.fetch_position_info(selection_key) # results_time = decoding_results.acausal_posterior.isel(intervals=0).time.values # position_info = position_info.loc[results_time[0] : results_time[-1]] -# env = ClusterlessDecodingV1.load_environments(selection_key)[0] -# spike_times, _ = ClusterlessDecodingV1.load_spike_data(selection_key) +# env = ClusterlessDecodingV1.fetch_environments(selection_key)[0] +# spike_times, _ = ClusterlessDecodingV1.fetch_spike_data(selection_key) # create_interactive_2D_decoding_figurl( diff --git a/notebooks/py_scripts/43_Decoding_SortedSpikes.py b/notebooks/py_scripts/43_Decoding_SortedSpikes.py index f753a38eb..8f51cd4a7 100644 --- a/notebooks/py_scripts/43_Decoding_SortedSpikes.py +++ b/notebooks/py_scripts/43_Decoding_SortedSpikes.py @@ -26,7 +26,6 @@ # This time, instead of extracting waveform features, we can proceed directly from the SpikeSortingOutput table to specify which units we want to decode. The rest of the decoding process is the same as before. # # -# ## SortedSpikesGroup # + from pathlib import Path @@ -35,35 +34,63 @@ dj.config.load( Path("../dj_local_conf.json").absolute() ) # load config for database connection info +# - + +# ## SortedSpikesGroup +# +# `SortedSpikesGroup` is a child table of `SpikeSortingOutput` in the spikesorting pipeline. It allows us to group the spikesorting results from multiple +# sources (e.g. multiple terode groups or intervals) into a single entry. Here we will group together the spiking of multiple tetrode groups to use for decoding. +# +# +# This table allows us filter units by their annotation labels from curation (e.g only include units labeled "good", exclude units labeled "noise") by defining parameters from `UnitSelectionParams`. When accessing data through `SortedSpikesGroup` the table will include only units with at least one label in `include_labels` and no labels in `exclude_labels`. We can look at those here: +# # + -from spyglass.spikesorting.merge import SpikeSortingOutput -import spyglass.spikesorting.v1 as sgs +from spyglass.spikesorting.analysis.v1.group import UnitSelectionParams +UnitSelectionParams().insert_default() + +# look at the filter set we'll use here +unit_filter_params_name = "default_exclusion" +print( + ( + UnitSelectionParams() + & {"unit_filter_params_name": unit_filter_params_name} + ).fetch1() +) +# look at full table +UnitSelectionParams() +# - + +# Now we can make our sorted spikes group with this unit selection parameter + +# + +from spyglass.spikesorting.spikesorting_merge import SpikeSortingOutput +import spyglass.spikesorting.v1 as sgs nwb_copy_file_name = "mediumnwb20230802_.nwb" sorter_keys = { "nwb_file_name": nwb_copy_file_name, - "sorter": "clusterless_thresholder", - "sorter_param_name": "default_clusterless", + "sorter": "mountainsort4", + "curation_id": 1, } - +# check the set of sorting we'll use (sgs.SpikeSortingSelection & sorter_keys) * SpikeSortingOutput.CurationV1 -# + -spikesorting_merge_ids = ( - (sgs.SpikeSortingSelection & sorter_keys) * SpikeSortingOutput.CurationV1 -).fetch("merge_id") - -spikesorting_merge_ids - # + from spyglass.decoding.v1.sorted_spikes import SortedSpikesGroup SortedSpikesGroup() # + +# get the merge_ids for the selected sorting +spikesorting_merge_ids = ( + (sgs.SpikeSortingSelection & sorter_keys) * SpikeSortingOutput.CurationV1 +).fetch("merge_id") + +# create a new sorted spikes group +unit_filter_params_name = "default_exclusion" SortedSpikesGroup().create_group( group_name="test_group", nwb_file_name=nwb_copy_file_name, @@ -71,17 +98,20 @@ {"spikesorting_merge_id": merge_id} for merge_id in spikesorting_merge_ids ], + unit_filter_params_name=unit_filter_params_name, ) - +# check the new group SortedSpikesGroup & { "nwb_file_name": nwb_copy_file_name, "sorted_spikes_group_name": "test_group", } # - +# look at the sorting within the group we just made SortedSpikesGroup.SortGroup & { "nwb_file_name": nwb_copy_file_name, "sorted_spikes_group_name": "test_group", + "unit_filter_params_name": unit_filter_params_name, } # ## Model parameters @@ -113,14 +143,10 @@ # # Now we can decode the position using the sorted spikes using the `SortedSpikesDecodingSelection` table. Here we assume that `PositionGroup` has been specified as in the clusterless decoding tutorial. -# + -from spyglass.decoding.v1.sorted_spikes import SortedSpikesDecodingSelection - -SortedSpikesDecodingSelection() - # + selection_key = { "sorted_spikes_group_name": "test_group", + "unit_filter_params_name": "default_exclusion", "position_group_name": "test_group", "decoding_param_name": "contfrag_sorted", "nwb_file_name": "mediumnwb20230802_.nwb", @@ -129,6 +155,8 @@ "estimate_decoding_params": False, } +from spyglass.decoding import SortedSpikesDecodingSelection + SortedSpikesDecodingSelection.insert1( selection_key, skip_duplicates=True, @@ -150,5 +178,8 @@ # We can load the results as before: -results = (SortedSpikesDecodingV1 & selection_key).load_results() +# + + +results = (SortedSpikesDecodingV1 & selection_key).fetch_results() results +# - diff --git a/notebooks/py_scripts/51_MUA_Detection.py b/notebooks/py_scripts/51_MUA_Detection.py new file mode 100644 index 000000000..506217553 --- /dev/null +++ b/notebooks/py_scripts/51_MUA_Detection.py @@ -0,0 +1,241 @@ +# --- +# jupyter: +# jupytext: +# text_representation: +# extension: .py +# format_name: light +# format_version: '1.5' +# jupytext_version: 1.16.0 +# kernelspec: +# display_name: spyglass +# language: python +# name: python3 +# --- + +# + +from pathlib import Path +import datajoint as dj + +dj.config.load( + Path("../dj_local_conf.json").absolute() +) # load config for database connection info +# - + +# # MUA Analysis and Detection +# +# NOTE: This notebook is a work in progress. It is not yet complete and may contain errors. + +# + +from spyglass.spikesorting.spikesorting_merge import SpikeSortingOutput +import spyglass.spikesorting.v1 as sgs + + +nwb_copy_file_name = "mediumnwb20230802_.nwb" + +sorter_keys = { + "nwb_file_name": nwb_copy_file_name, + "sorter": "clusterless_thresholder", + "sorter_param_name": "default_clusterless", +} + +(sgs.SpikeSortingSelection & sorter_keys) * SpikeSortingOutput.CurationV1 + +# + +spikesorting_merge_ids = ( + (sgs.SpikeSortingSelection & sorter_keys) * SpikeSortingOutput.CurationV1 +).fetch("merge_id") + +spikesorting_merge_ids + +# + +from spyglass.spikesorting.unit_inclusion_merge import ( + ImportedUnitInclusionV1, + UnitInclusionOutput, +) + +ImportedUnitInclusionV1().insert_all_units(spikesorting_merge_ids) + +UnitInclusionOutput.ImportedUnitInclusionV1() & [ + {"spikesorting_merge_id": id} for id in spikesorting_merge_ids +] + +# + +from spyglass.spikesorting.unit_inclusion_merge import ( + ImportedUnitInclusionV1, + UnitInclusionOutput, +) + +ImportedUnitInclusionV1().insert_all_units(spikesorting_merge_ids) + +UnitInclusionOutput.ImportedUnitInclusionV1() & [ + {"spikesorting_merge_id": id} for id in spikesorting_merge_ids +] + +# + +from spyglass.spikesorting.unit_inclusion_merge import SortedSpikesGroup + +unit_inclusion_merge_ids = ( + UnitInclusionOutput.ImportedUnitInclusionV1 + & [{"spikesorting_merge_id": id} for id in spikesorting_merge_ids] +).fetch("merge_id") + +SortedSpikesGroup().create_group( + group_name="test_group", + nwb_file_name=nwb_copy_file_name, + unit_inclusion_merge_ids=unit_inclusion_merge_ids, +) + +group_key = { + "nwb_file_name": nwb_copy_file_name, + "sorted_spikes_group_name": "test_group", +} + +SortedSpikesGroup & group_key +# - + +SortedSpikesGroup.Units() & group_key + +# An example of how to get spike times + +spike_times = SortedSpikesGroup.fetch_spike_data(group_key) +spike_times[0] + +# + +from spyglass.position import PositionOutput + +position_merge_id = ( + PositionOutput.TrodesPosV1 + & { + "nwb_file_name": nwb_copy_file_name, + "interval_list_name": "pos 0 valid times", + "trodes_pos_params_name": "default_decoding", + } +).fetch1("merge_id") + +position_info = ( + (PositionOutput & {"merge_id": position_merge_id}) + .fetch1_dataframe() + .dropna() +) +position_info + +# + +time_ind_slice = slice(63_000, 70_000) +time = position_info.index[time_ind_slice] + +SortedSpikesGroup.get_spike_indicator(group_key, time) + +# + +import matplotlib.pyplot as plt + +fig, axes = plt.subplots(2, 1, sharex=True, figsize=(15, 4)) +multiunit_firing_rate = SortedSpikesGroup.get_firing_rate( + group_key, time, multiunit=True +) +axes[0].plot( + time, + multiunit_firing_rate, +) +axes[0].set_ylabel("firing rate (Hz)") +axes[0].set_title("multiunit") +axes[1].fill_between( + time, position_info["speed"].iloc[time_ind_slice], color="lightgrey" +) +axes[1].set_ylabel("speed (cm/s)") +axes[1].set_xlabel("time (s)") + +# + +from spyglass.mua.v1.mua import MuaEventsParameters, MuaEventsV1 + +MuaEventsParameters().insert_default() +MuaEventsParameters() + +# + +selection_key = { + "mua_param_name": "default", + "nwb_file_name": nwb_copy_file_name, + "sorted_spikes_group_name": "test_group", + "pos_merge_id": position_merge_id, + "artifact_interval_list_name": "test_artifact_times", +} + +MuaEventsV1.populate(selection_key) +# - + +MuaEventsV1 & selection_key + +mua_times = (MuaEventsV1 & selection_key).fetch1_dataframe() +mua_times + +# + +import matplotlib.pyplot as plt +import numpy as np + +fig, axes = plt.subplots(2, 1, sharex=True, figsize=(15, 4)) +axes[0].plot( + time, + multiunit_firing_rate, +) +axes[0].set_ylabel("firing rate (Hz)") +axes[0].set_title("multiunit") +axes[1].fill_between( + time, position_info["speed"].iloc[time_ind_slice], color="lightgrey" +) +axes[1].set_ylabel("speed (cm/s)") +axes[1].set_xlabel("time (s)") + +in_bounds = np.logical_and( + mua_times.start_time >= time[0], mua_times.end_time <= time[-1] +) + +for mua_time in mua_times.loc[in_bounds].itertuples(): + axes[0].axvspan( + mua_time.start_time, mua_time.end_time, color="red", alpha=0.3 + ) + axes[1].axvspan( + mua_time.start_time, mua_time.end_time, color="red", alpha=0.3 + ) +axes[1].set_ylim((0, 80)) +axes[1].axhline(4, color="black", linestyle="--") +axes[1].set_xlim((time[0], time[-1])) + +# + +from spyglass.common import IntervalList + +IntervalList() & { + "nwb_file_name": nwb_copy_file_name, + "pipeline": "spikesorting_artifact_v1", +} +# - + +( + sgs.ArtifactDetectionParameters + * sgs.SpikeSortingRecording + * sgs.ArtifactDetectionSelection +) + +SpikeSortingOutput.CurationV1() * ( + sgs.ArtifactDetectionParameters + * sgs.SpikeSortingRecording + * sgs.ArtifactDetectionSelection +) + +( + IntervalList() + & { + "nwb_file_name": nwb_copy_file_name, + "pipeline": "spikesorting_artifact_v1", + } +).proj(artifact_id="interval_list_name") + +sgs.SpikeSortingRecording() * sgs.ArtifactDetectionSelection() + +SpikeSortingOutput.CurationV1() * sgs.SpikeSortingRecording() + +IntervalList.insert1( + { + "nwb_file_name": nwb_copy_file_name, + "interval_list_name": "test_artifact_times", + "valid_times": [], + } +) diff --git a/pyproject.toml b/pyproject.toml index 16be96baf..fa50e8ddd 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -116,17 +116,17 @@ ignore-words-list = 'nevers' [tool.pytest.ini_options] minversion = "7.0" addopts = [ - "-sv", - # "--sw", # stepwise: resume with next test after failure - # "--pdb", # drop into debugger on failure - "-p no:warnings", - # "--no-teardown", # don't teardown the database after tests - "--quiet-spy", # don't show logging from spyglass - "--show-capture=no", - "--pdbcls=IPython.terminal.debugger:TerminalPdb", # use ipython debugger - "--cov=spyglass", - "--cov-report=term-missing", - "--no-cov-on-fail", + "-sv", + # "--sw", # stepwise: resume with next test after failure + # "--pdb", # drop into debugger on failure + "-p no:warnings", + # "--no-teardown", # don't teardown the database after tests + "--quiet-spy", # don't show logging from spyglass + "--show-capture=no", + "--pdbcls=IPython.terminal.debugger:TerminalPdb", # use ipython debugger + "--cov=spyglass", + "--cov-report=term-missing", + "--no-cov-on-fail", ] testpaths = ["tests"] log_level = "INFO" @@ -134,19 +134,19 @@ log_level = "INFO" [tool.coverage.run] source = ["*/src/spyglass/*"] omit = [ # which submodules have no tests - "*/__init__.py", - "*/_version.py", - "*/cli/*", - # "*/common/*", - "*/data_import/*", - "*/decoding/*", - "*/figurl_views/*", - # "*/lfp/*", - "*/linearization/*", - "*/lock/*", - "*/position/*", - "*/ripple/*", - "*/sharing/*", - "*/spikesorting/*", - # "*/utils/*", + "*/__init__.py", + "*/_version.py", + "*/cli/*", + # "*/common/*", + "*/data_import/*", + "*/decoding/*", + "*/figurl_views/*", + # "*/lfp/*", + "*/linearization/*", + "*/lock/*", + "*/position/*", + "*/ripple/*", + "*/sharing/*", + "*/spikesorting/*", + # "*/utils/*", ] diff --git a/src/spyglass/__init__.py b/src/spyglass/__init__.py index 524235c1a..bfe9713c3 100644 --- a/src/spyglass/__init__.py +++ b/src/spyglass/__init__.py @@ -1,4 +1,4 @@ -from .settings import config # ensure loaded config dirs +from spyglass.settings import config # ensure loaded config dirs try: import ndx_franklab_novela diff --git a/src/spyglass/cli/__init__.py b/src/spyglass/cli/__init__.py index 4b7029b4e..242b40b61 100644 --- a/src/spyglass/cli/__init__.py +++ b/src/spyglass/cli/__init__.py @@ -1 +1 @@ -from .cli import cli +from spyglass.cli import cli diff --git a/src/spyglass/common/__init__.py b/src/spyglass/common/__init__.py index 79219f277..75a6c7c2e 100644 --- a/src/spyglass/common/__init__.py +++ b/src/spyglass/common/__init__.py @@ -1,16 +1,6 @@ -from ..utils.dj_mixin import SpyglassMixin # isort:skip +from spyglass.utils.dj_mixin import SpyglassMixin # isort:skip -from ..settings import prepopulate -from ..utils.nwb_helper_fn import ( - close_nwb_files, - estimate_sampling_rate, - get_data_interface, - get_electrode_indices, - get_nwb_file, - get_raw_eseries, - get_valid_intervals, -) -from .common_behav import ( +from spyglass.common.common_behav import ( PositionIntervalMap, PositionSource, RawPosition, @@ -18,7 +8,7 @@ VideoFile, convert_epoch_interval_name_to_position_interval_name, ) -from .common_device import ( +from spyglass.common.common_device import ( CameraDevice, DataAcquisitionDevice, DataAcquisitionDeviceAmplifier, @@ -26,8 +16,8 @@ Probe, ProbeType, ) -from .common_dio import DIOEvents -from .common_ephys import ( +from spyglass.common.common_dio import DIOEvents +from spyglass.common.common_ephys import ( LFP, Electrode, ElectrodeGroup, @@ -37,8 +27,8 @@ Raw, SampleCount, ) -from .common_filter import FirFilterParameters -from .common_interval import ( +from spyglass.common.common_filter import FirFilterParameters +from spyglass.common.common_interval import ( IntervalList, interval_list_censor, interval_list_contains, @@ -49,14 +39,14 @@ interval_list_union, intervals_by_length, ) -from .common_lab import Institution, Lab, LabMember, LabTeam -from .common_nwbfile import ( +from spyglass.common.common_lab import Institution, Lab, LabMember, LabTeam +from spyglass.common.common_nwbfile import ( AnalysisNwbfile, AnalysisNwbfileKachery, Nwbfile, NwbfileKachery, ) -from .common_position import ( +from spyglass.common.common_position import ( IntervalLinearizationSelection, IntervalLinearizedPosition, IntervalPositionInfo, @@ -66,13 +56,23 @@ PositionVideo, TrackGraph, ) -from .common_region import BrainRegion -from .common_sensors import SensorData -from .common_session import Session, SessionGroup -from .common_subject import Subject -from .common_task import Task, TaskEpoch -from .populate_all_common import populate_all_common -from .prepopulate import populate_from_yaml, prepopulate_default +from spyglass.common.common_region import BrainRegion +from spyglass.common.common_sensors import SensorData +from spyglass.common.common_session import Session, SessionGroup +from spyglass.common.common_subject import Subject +from spyglass.common.common_task import Task, TaskEpoch +from spyglass.common.populate_all_common import populate_all_common +from spyglass.common.prepopulate import populate_from_yaml, prepopulate_default +from spyglass.settings import prepopulate +from spyglass.utils.nwb_helper_fn import ( + close_nwb_files, + estimate_sampling_rate, + get_data_interface, + get_electrode_indices, + get_nwb_file, + get_raw_eseries, + get_valid_intervals, +) if prepopulate: prepopulate_default() diff --git a/src/spyglass/common/common_position.py b/src/spyglass/common/common_position.py index 7461f0c72..feb25a2ed 100644 --- a/src/spyglass/common/common_position.py +++ b/src/spyglass/common/common_position.py @@ -1,5 +1,4 @@ import bottleneck -import cv2 import datajoint as dj import matplotlib.pyplot as plt import numpy as np @@ -642,6 +641,8 @@ def make_video( arrow_radius=15, circle_radius=8, ): + import cv2 # noqa: F401 + RGB_PINK = (234, 82, 111) RGB_YELLOW = (253, 231, 76) RGB_WHITE = (255, 255, 255) diff --git a/src/spyglass/common/populate_all_common.py b/src/spyglass/common/populate_all_common.py index 018a6fd68..b2fa7d760 100644 --- a/src/spyglass/common/populate_all_common.py +++ b/src/spyglass/common/populate_all_common.py @@ -14,7 +14,6 @@ from spyglass.common.common_nwbfile import Nwbfile from spyglass.common.common_session import Session from spyglass.common.common_task import TaskEpoch -from spyglass.spikesorting.imported import ImportedSpikeSorting from spyglass.utils import logger @@ -60,4 +59,6 @@ def populate_all_common(nwb_file_name): RawPosition.populate(fp) logger.info("Populate ImportedSpikeSorting...") + from spyglass.spikesorting.imported import ImportedSpikeSorting + ImportedSpikeSorting.populate(fp) diff --git a/src/spyglass/data_import/__init__.py b/src/spyglass/data_import/__init__.py index 9c68cf038..34b9d4822 100644 --- a/src/spyglass/data_import/__init__.py +++ b/src/spyglass/data_import/__init__.py @@ -1,2 +1,2 @@ # TODO: change naming to avoid match between module and function -from .insert_sessions import insert_sessions +from spyglass.data_import.insert_sessions import insert_sessions diff --git a/src/spyglass/decoding/decoding_merge.py b/src/spyglass/decoding/decoding_merge.py index 7e6a2d90a..1e15ba859 100644 --- a/src/spyglass/decoding/decoding_merge.py +++ b/src/spyglass/decoding/decoding_merge.py @@ -84,83 +84,68 @@ def cleanup(self, dry_run=False): except (PermissionError, FileNotFoundError): logger.warning(f"Unable to remove {path}, skipping") - @property - def source_class_dict(self) -> dict: - """Dictionary of source class names to source classes - - { - 'ClusterlessDecodingV1': spy...ClusterlessDecodingV1, - 'SortedSpikesDecodingV1': spy...SortedSpikesDecodingV1 - } - - Returns - ------- - dict - Dictionary of source class names to source classes - """ - if not self._source_class_dict: - self._ensure_dependencies_loaded() - module = inspect.getmodule(self) - for part_name in self.parts(): - part_name = to_camel_case(part_name.split("__")[-1].strip("`")) - part = getattr(module, part_name) - self._source_class_dict[part_name] = part - return self._source_class_dict - - @classmethod - def _get_source_class(cls, key): - # CB: By making this a property, we can generate the source_class_dict - # without a key. Previously failed on empty table - # This demonstrates pipeline-specific implementation. See also - # merge_restrict_class edits that centralize this logic. - return cls.source_class_dict[(cls & key).fetch1("source")] - @classmethod - def load_results(cls, key): - decoding_selection_key = cls.merge_get_parent(key).fetch1("KEY") - source_class = cls._get_source_class(key) - return (source_class & decoding_selection_key).load_results() + def fetch_results(cls, key): + return cls().merge_get_parent_class(key).fetch_results() @classmethod - def load_model(cls, key): - decoding_selection_key = cls.merge_get_parent(key).fetch1("KEY") - source_class = cls._get_source_class(key) - return (source_class & decoding_selection_key).load_model() + def fetch_model(cls, key): + return cls().merge_get_parent_class(key).fetch_model() @classmethod - def load_environments(cls, key): + def fetch_environments(cls, key): decoding_selection_key = cls.merge_get_parent(key).fetch1("KEY") - source_class = cls._get_source_class(key) - return source_class.load_environments(decoding_selection_key) + return ( + cls() + .merge_get_parent_class(key) + .fetch_environments(decoding_selection_key) + ) @classmethod - def load_position_info(cls, key): + def fetch_position_info(cls, key): decoding_selection_key = cls.merge_get_parent(key).fetch1("KEY") - source_class = cls._get_source_class(key) - return source_class.load_position_info(decoding_selection_key) + return ( + cls() + .merge_get_parent_class(key) + .fetch_position_info(decoding_selection_key) + ) @classmethod - def load_linear_position_info(cls, key): + def fetch_linear_position_info(cls, key): decoding_selection_key = cls.merge_get_parent(key).fetch1("KEY") - source_class = cls._get_source_class(key) - return source_class.load_linear_position_info(decoding_selection_key) + return ( + cls() + .merge_get_parent_class(key) + .fetch_linear_position_info(decoding_selection_key) + ) @classmethod - def load_spike_data(cls, key, filter_by_interval=True): + def fetch_spike_data(cls, key, filter_by_interval=True): decoding_selection_key = cls.merge_get_parent(key).fetch1("KEY") - source_class = cls._get_source_class(key) - return source_class.load_linear_position_info( - decoding_selection_key, filter_by_interval=filter_by_interval + return ( + cls() + .merge_get_parent_class(key) + .fetch_linear_position_info( + decoding_selection_key, filter_by_interval=filter_by_interval + ) ) @classmethod def create_decoding_view(cls, key, head_direction_name="head_orientation"): - results = cls.load_results(key) - posterior = results.acausal_posterior.unstack("state_bins").sum("state") - env = cls.load_environments(key)[0] + results = cls.fetch_results(key) + posterior = ( + results.squeeze() + .acausal_posterior.unstack("state_bins") + .drop_sel(state=["Local", "No-Spike"], errors="ignore") + .sum("state") + ) + posterior /= posterior.sum("position") + env = cls.fetch_environments(key)[0] if "x_position" in results.coords: - position_info, position_variable_names = cls.load_position_info(key) + position_info, position_variable_names = cls.fetch_position_info( + key + ) # Not 1D bin_size = ( np.nanmedian(np.diff(np.unique(results.x_position.values))), @@ -180,9 +165,8 @@ def create_decoding_view(cls, key, head_direction_name="head_orientation"): ( position_info, position_variable_names, - ) = cls.load_linear_position_info(key) + ) = cls.fetch_linear_position_info(key) return create_1D_decode_view( posterior=posterior, linear_position=position_info["linear_position"], - ref_time_sec=position_info.index[0], ) diff --git a/src/spyglass/decoding/v0/clusterless.py b/src/spyglass/decoding/v0/clusterless.py index e5577225d..221d39d83 100644 --- a/src/spyglass/decoding/v0/clusterless.py +++ b/src/spyglass/decoding/v0/clusterless.py @@ -38,7 +38,6 @@ ) except ImportError as e: logger.warning(e) -from ripple_detection import get_multiunit_population_firing_rate from tqdm.auto import tqdm from spyglass.common.common_behav import ( @@ -55,12 +54,12 @@ convert_classes_to_dict, restore_classes, ) -from spyglass.spikesorting.spikesorting_curation import ( +from spyglass.spikesorting.v0.spikesorting_curation import ( CuratedSpikeSorting, CuratedSpikeSortingSelection, Curation, ) -from spyglass.spikesorting.spikesorting_sorting import ( +from spyglass.spikesorting.v0.spikesorting_sorting import ( SpikeSorting, SpikeSortingSelection, ) @@ -624,88 +623,6 @@ def fetch1(self, *args, **kwargs) -> dict: return restore_classes(super().fetch1(*args, **kwargs)) -@schema -class MultiunitFiringRate(SpyglassMixin, dj.Computed): - """Computes the population multiunit firing rate from the spikes in - MarksIndicator.""" - - definition = """ - -> UnitMarksIndicator - --- - -> AnalysisNwbfile - multiunit_firing_rate_object_id: varchar(40) - """ - - def make(self, key): - marks = (UnitMarksIndicator & key).fetch_xarray() - multiunit_spikes = (np.any(~np.isnan(marks.values), axis=1)).astype( - float - ) - multiunit_firing_rate = pd.DataFrame( - get_multiunit_population_firing_rate( - multiunit_spikes, key["sampling_rate"] - ), - index=marks.time, - columns=["firing_rate"], - ) - - # Insert into analysis nwb file - nwb_analysis_file = AnalysisNwbfile() - key["analysis_file_name"] = nwb_analysis_file.create( - key["nwb_file_name"] - ) - - key["multiunit_firing_rate_object_id"] = ( - nwb_analysis_file.add_nwb_object( - analysis_file_name=key["analysis_file_name"], - nwb_object=multiunit_firing_rate.reset_index(), - ) - ) - - nwb_analysis_file.add( - nwb_file_name=key["nwb_file_name"], - analysis_file_name=key["analysis_file_name"], - ) - - self.insert1(key) - - def fetch1_dataframe(self) -> pd.DataFrame: - """Convenience function for returning the first dataframe""" - return self.fetch_dataframe()[0] - - def fetch_dataframe(self) -> list[pd.DataFrame]: - """Fetches the multiunit firing rate as a list of pandas dataframes""" - return [ - data["multiunit_firing_rate"].set_index("time") - for data in self.fetch_nwb() - ] - - -@schema -class MultiunitHighSynchronyEventsParameters(SpyglassMixin, dj.Manual): - """Params to extract times of high mulitunit activity during immobility.""" - - definition = """ - param_name : varchar(80) # a name for this set of parameters - --- - minimum_duration = 0.015 : float # minimum duration of event (in seconds) - zscore_threshold = 2.0 : float # threshold event must cross to be considered (in std. dev.) - close_event_threshold = 0.0 : float # events closer than this will be excluded (in seconds) - """ - - def insert_default(self): - """Insert the default parameter set""" - self.insert1( - { - "param_name": "default", - "minimum_duration": 0.015, - "zscore_threshold": 2.0, - "close_event_threshold": 0.0, - }, - skip_duplicates=True, - ) - - def get_decoding_data_for_epoch( nwb_file_name: str, interval_list_name: str, diff --git a/src/spyglass/decoding/v0/sorted_spikes.py b/src/spyglass/decoding/v0/sorted_spikes.py index acfc501cf..8a7013564 100644 --- a/src/spyglass/decoding/v0/sorted_spikes.py +++ b/src/spyglass/decoding/v0/sorted_spikes.py @@ -44,7 +44,7 @@ convert_classes_to_dict, restore_classes, ) -from spyglass.spikesorting.spikesorting_curation import CuratedSpikeSorting +from spyglass.spikesorting.v0.spikesorting_curation import CuratedSpikeSorting from spyglass.utils import SpyglassMixin, logger schema = dj.schema("decoding_sortedspikes") diff --git a/src/spyglass/decoding/v0/visualization_2D_view.py b/src/spyglass/decoding/v0/visualization_2D_view.py index 14dcd204c..f0264f102 100644 --- a/src/spyglass/decoding/v0/visualization_2D_view.py +++ b/src/spyglass/decoding/v0/visualization_2D_view.py @@ -3,10 +3,6 @@ import numpy as np import sortingview.views.franklab as vvf import xarray as xr -from replay_trajectory_classification.environments import ( - get_grid, - get_track_interior, -) def create_static_track_animation( diff --git a/src/spyglass/decoding/v1/clusterless.py b/src/spyglass/decoding/v1/clusterless.py index 1751ff8eb..d69daf57f 100644 --- a/src/spyglass/decoding/v1/clusterless.py +++ b/src/spyglass/decoding/v1/clusterless.py @@ -107,14 +107,14 @@ def make(self, key): ( position_info, position_variable_names, - ) = self.load_position_info(key) + ) = self.fetch_position_info(key) # Get the waveform features for the selected units # Don't need to filter by interval since the non_local_detector code will do that ( spike_times, spike_waveform_features, - ) = self.load_spike_data(key, filter_by_interval=False) + ) = self.fetch_spike_data(key, filter_by_interval=False) # Get the encoding and decoding intervals encoding_interval = ( @@ -274,14 +274,14 @@ def make(self, key): DecodingOutput.insert1(orig_key, skip_duplicates=True) - def load_results(self): + def fetch_results(self): return ClusterlessDetector.load_results(self.fetch1("results_path")) - def load_model(self): + def fetch_model(self): return ClusterlessDetector.load_model(self.fetch1("classifier_path")) @staticmethod - def load_environments(key): + def fetch_environments(key): model_params = ( DecodingParameters & {"decoding_param_name": key["decoding_param_name"]} @@ -297,7 +297,7 @@ def load_environments(key): ( position_info, position_variable_names, - ) = ClusterlessDecodingV1.load_position_info(key) + ) = ClusterlessDecodingV1.fetch_position_info(key) classifier = ClusterlessDetector(**decoding_params) classifier.initialize_environments( @@ -337,7 +337,7 @@ def _get_interval_range(key): ) @staticmethod - def load_position_info(key): + def fetch_position_info(key): position_group_key = { "position_group_name": key["position_group_name"], "nwb_file_name": key["nwb_file_name"], @@ -362,10 +362,10 @@ def load_position_info(key): return position_info, position_variable_names @staticmethod - def load_linear_position_info(key): - environment = ClusterlessDecodingV1.load_environments(key)[0] + def fetch_linear_position_info(key): + environment = ClusterlessDecodingV1.fetch_environments(key)[0] - position_df = ClusterlessDecodingV1.load_position_info(key)[0] + position_df = ClusterlessDecodingV1.fetch_position_info(key)[0] position_variable_names = (PositionGroup & key).fetch1( "position_variables" ) @@ -390,7 +390,7 @@ def load_linear_position_info(key): ) @staticmethod - def load_spike_data(key, filter_by_interval=True): + def fetch_spike_data(key, filter_by_interval=True): waveform_keys = ( ( UnitWaveformFeaturesGroup.UnitFeatures @@ -428,7 +428,7 @@ def load_spike_data(key, filter_by_interval=True): def get_spike_indicator(cls, key, time): time = np.asarray(time) min_time, max_time = time[[0, -1]] - spike_times = cls.load_spike_data(key)[0] + spike_times = cls.fetch_spike_data(key)[0] spike_indicator = np.zeros((len(time), len(spike_times))) for ind, times in enumerate(spike_times): @@ -465,12 +465,12 @@ def get_ahead_behind_distance(self): # TODO: allow specification of track graph # TODO: Handle decode intervals, store in table - classifier = self.load_model() - results = self.load_results() + classifier = self.fetch_model() + results = self.fetch_results() posterior = results.acausal_posterior.unstack("state_bins").sum("state") if getattr(classifier.environments[0], "track_graph") is not None: - linear_position_info = self.load_linear_position_info( + linear_position_info = self.fetch_linear_position_info( self.fetch1("KEY") ) @@ -495,7 +495,7 @@ def get_ahead_behind_distance(self): classifier.environments[0].track_graph, *traj_data ) else: - position_info = self.load_position_info(self.fetch1("KEY")) + position_info = self.fetch_position_info(self.fetch1("KEY")) map_position = analysis.maximum_a_posteriori_estimate(posterior) orientation_name = ( diff --git a/src/spyglass/decoding/v1/sorted_spikes.py b/src/spyglass/decoding/v1/sorted_spikes.py index 40041691a..0d3b3af32 100644 --- a/src/spyglass/decoding/v1/sorted_spikes.py +++ b/src/spyglass/decoding/v1/sorted_spikes.py @@ -29,43 +29,15 @@ ) # noqa: F401 from spyglass.position.position_merge import PositionOutput # noqa: F401 from spyglass.settings import config -from spyglass.spikesorting.merge import SpikeSortingOutput # noqa: F401 +from spyglass.spikesorting.analysis.v1.group import SortedSpikesGroup +from spyglass.spikesorting.spikesorting_merge import ( + SpikeSortingOutput, +) # noqa: F401 from spyglass.utils import SpyglassMixin, logger schema = dj.schema("decoding_sorted_spikes_v1") -@schema -class SortedSpikesGroup(SpyglassMixin, dj.Manual): - definition = """ - -> Session - sorted_spikes_group_name: varchar(80) - """ - - class SortGroup(SpyglassMixin, dj.Part): - definition = """ - -> SortedSpikesGroup - -> SpikeSortingOutput.proj(spikesorting_merge_id='merge_id') - """ - - def create_group( - self, group_name: str, nwb_file_name: str, keys: list[dict] - ): - group_key = { - "sorted_spikes_group_name": group_name, - "nwb_file_name": nwb_file_name, - } - self.insert1( - group_key, - skip_duplicates=True, - ) - for key in keys: - self.SortGroup.insert1( - {**key, **group_key}, - skip_duplicates=True, - ) - - @schema class SortedSpikesDecodingSelection(SpyglassMixin, dj.Manual): definition = """ @@ -105,11 +77,11 @@ def make(self, key): ( position_info, position_variable_names, - ) = self.load_position_info(key) + ) = self.fetch_position_info(key) # Get the spike times for the selected units # Don't need to filter by interval since the non_local_detector code will do that - spike_times = self.load_spike_data(key, filter_by_interval=False) + spike_times = self.fetch_spike_data(key, filter_by_interval=False) # Get the encoding and decoding intervals encoding_interval = ( @@ -266,14 +238,14 @@ def make(self, key): DecodingOutput.insert1(orig_key, skip_duplicates=True) - def load_results(self): + def fetch_results(self): return SortedSpikesDetector.load_results(self.fetch1("results_path")) - def load_model(self): + def fetch_model(self): return SortedSpikesDetector.load_model(self.fetch1("classifier_path")) @staticmethod - def load_environments(key): + def fetch_environments(key): model_params = ( DecodingParameters & {"decoding_param_name": key["decoding_param_name"]} @@ -289,7 +261,7 @@ def load_environments(key): ( position_info, position_variable_names, - ) = SortedSpikesDecodingV1.load_position_info(key) + ) = SortedSpikesDecodingV1.fetch_position_info(key) classifier = SortedSpikesDetector(**decoding_params) classifier.initialize_environments( @@ -329,7 +301,7 @@ def _get_interval_range(key): ) @staticmethod - def load_position_info(key): + def fetch_position_info(key): position_group_key = { "position_group_name": key["position_group_name"], "nwb_file_name": key["nwb_file_name"], @@ -353,10 +325,10 @@ def load_position_info(key): return position_info, position_variable_names @staticmethod - def load_linear_position_info(key): - environment = SortedSpikesDecodingV1.load_environments(key)[0] + def fetch_linear_position_info(key): + environment = SortedSpikesDecodingV1.fetch_environments(key)[0] - position_df = SortedSpikesDecodingV1.load_position_info(key)[0] + position_df = SortedSpikesDecodingV1.fetch_position_info(key)[0] position_variable_names = (PositionGroup & key).fetch1( "position_variables" ) @@ -379,34 +351,15 @@ def load_linear_position_info(key): ) @staticmethod - def load_spike_data(key, filter_by_interval=True): - merge_ids = ( - ( - SortedSpikesGroup.SortGroup - & { - "nwb_file_name": key["nwb_file_name"], - "sorted_spikes_group_name": key["sorted_spikes_group_name"], - } - ) - ).fetch("spikesorting_merge_id") - - spike_times = [] - for merge_id in merge_ids: - nwb_file = SpikeSortingOutput().fetch_nwb({"merge_id": merge_id})[0] - - if "object_id" in nwb_file: - # v1 spikesorting - spike_times.extend( - nwb_file["object_id"]["spike_times"].to_list() - ) - elif "units" in nwb_file: - # v0 spikesorting - spike_times.extend(nwb_file["units"]["spike_times"].to_list()) - + def fetch_spike_data(key, filter_by_interval=True, time_slice=None): + spike_times = SortedSpikesGroup.fetch_spike_data(key) if not filter_by_interval: return spike_times - min_time, max_time = SortedSpikesDecodingV1._get_interval_range(key) + if time_slice is None: + min_time, max_time = SortedSpikesDecodingV1._get_interval_range(key) + else: + min_time, max_time = time_slice.start, time_slice.stop new_spike_times = [] for elec_spike_times in spike_times: @@ -417,48 +370,12 @@ def load_spike_data(key, filter_by_interval=True): return new_spike_times - @classmethod - def get_spike_indicator(cls, key, time): - time = np.asarray(time) - min_time, max_time = time[[0, -1]] - spike_times = cls.load_spike_data(key) - spike_indicator = np.zeros((len(time), len(spike_times))) - - for ind, times in enumerate(spike_times): - times = times[np.logical_and(times >= min_time, times <= max_time)] - spike_indicator[:, ind] = np.bincount( - np.digitize(times, time[1:-1]), - minlength=time.shape[0], - ) - - return spike_indicator - - @classmethod - def get_firing_rate(cls, key, time, multiunit=False): - spike_indicator = cls.get_spike_indicator(key, time) - if spike_indicator.ndim == 1: - spike_indicator = spike_indicator[:, np.newaxis] - - sampling_frequency = 1 / np.median(np.diff(time)) - - if multiunit: - spike_indicator = spike_indicator.sum(axis=1, keepdims=True) - return np.stack( - [ - get_multiunit_population_firing_rate( - indicator[:, np.newaxis], sampling_frequency - ) - for indicator in spike_indicator.T - ], - axis=1, - ) - def spike_times_sorted_by_place_field_peak(self, time_slice=None): if time_slice is None: time_slice = slice(-np.inf, np.inf) - spike_times = self.load_spike_data(self.proj()) - classifier = self.load_model() + spike_times = self.fetch_spike_data(self.fetch1()) + classifier = self.fetch_model() new_spike_times = {} @@ -479,19 +396,28 @@ def spike_times_sorted_by_place_field_peak(self, time_slice=None): for neuron_ind in neuron_sort_ind ] - def get_ahead_behind_distance(self): - # TODO: allow specification of specific time interval - # TODO: allow specification of track graph - # TODO: Handle decode intervals, store in table + def get_ahead_behind_distance(self, track_graph=None, time_slice=None): + # TODO: store in table - classifier = self.load_model() - results = self.load_results() - posterior = results.acausal_posterior.unstack("state_bins").sum("state") + if time_slice is None: + time_slice = slice(-np.inf, np.inf) + + classifier = self.fetch_model() + posterior = ( + self.fetch_results() + .acausal_posterior.sel(time=time_slice) + .squeeze() + .unstack("state_bins") + .sum("state") + ) - if classifier.environments[0].track_graph is not None: - linear_position_info = self.load_linear_position_info( + if track_graph is None: + track_graph = classifier.environments[0].track_graph + + if track_graph is not None: + linear_position_info = self.fetch_linear_position_info( self.fetch1("KEY") - ) + ).loc[time_slice] orientation_name = ( "orientation" @@ -501,7 +427,7 @@ def get_ahead_behind_distance(self): traj_data = analysis.get_trajectory_data( posterior=posterior, - track_graph=classifier.environments[0].track_graph, + track_graph=track_graph, decoder=classifier, actual_projected_position=linear_position_info[ ["projected_x_position", "projected_y_position"] @@ -510,11 +436,11 @@ def get_ahead_behind_distance(self): actual_orientation=linear_position_info[orientation_name], ) - return analysis.get_ahead_behind_distance( - classifier.environments[0].track_graph, *traj_data - ) + return analysis.get_ahead_behind_distance(track_graph, *traj_data) else: - position_info = self.load_position_info(self.fetch1("KEY")) + position_info = self.fetch_position_info(self.fetch1("KEY")).loc[ + time_slice + ] map_position = analysis.maximum_a_posteriori_estimate(posterior) orientation_name = ( diff --git a/src/spyglass/decoding/v1/waveform_features.py b/src/spyglass/decoding/v1/waveform_features.py index b332df45e..044ff979a 100644 --- a/src/spyglass/decoding/v1/waveform_features.py +++ b/src/spyglass/decoding/v1/waveform_features.py @@ -9,11 +9,11 @@ from spyglass.common.common_nwbfile import AnalysisNwbfile from spyglass.settings import temp_dir -from spyglass.spikesorting.merge import SpikeSortingOutput +from spyglass.spikesorting.spikesorting_merge import SpikeSortingOutput from spyglass.spikesorting.v1 import SpikeSortingSelection from spyglass.utils import SpyglassMixin -schema = dj.schema("waveform_features") +schema = dj.schema("decoding_waveform_features") @schema diff --git a/src/spyglass/lfp/__init__.py b/src/spyglass/lfp/__init__.py index ec2198930..baa5e6d8f 100644 --- a/src/spyglass/lfp/__init__.py +++ b/src/spyglass/lfp/__init__.py @@ -1,3 +1,3 @@ -from spyglass.lfp.lfp_merge import LFPOutput from spyglass.lfp.lfp_electrode import LFPElectrodeGroup from spyglass.lfp.lfp_imported import ImportedLFP +from spyglass.lfp.lfp_merge import LFPOutput diff --git a/src/spyglass/lfp/analysis/v1/__init__.py b/src/spyglass/lfp/analysis/v1/__init__.py index 530fd6769..0557c9d86 100644 --- a/src/spyglass/lfp/analysis/v1/__init__.py +++ b/src/spyglass/lfp/analysis/v1/__init__.py @@ -1 +1 @@ -from spyglass.lfp.analysis.v1.lfp_band import LFPBandV1, LFPBandSelection +from spyglass.lfp.analysis.v1.lfp_band import LFPBandSelection, LFPBandV1 diff --git a/src/spyglass/lfp/v1/__init__.py b/src/spyglass/lfp/v1/__init__.py index 64ad9c72a..f415ab526 100644 --- a/src/spyglass/lfp/v1/__init__.py +++ b/src/spyglass/lfp/v1/__init__.py @@ -1,9 +1,5 @@ # flake8: noqa -from spyglass.lfp.v1.lfp import ( - LFPV1, - LFPElectrodeGroup, - LFPSelection, -) +from spyglass.lfp.v1.lfp import LFPV1, LFPElectrodeGroup, LFPSelection from spyglass.lfp.v1.lfp_artifact import ( LFPArtifactDetection, LFPArtifactDetectionParameters, diff --git a/src/spyglass/lfp/v1/lfp.py b/src/spyglass/lfp/v1/lfp.py index 3ef33244c..ecfbd6228 100644 --- a/src/spyglass/lfp/v1/lfp.py +++ b/src/spyglass/lfp/v1/lfp.py @@ -14,8 +14,6 @@ from spyglass.common.common_nwbfile import AnalysisNwbfile from spyglass.common.common_session import Session # noqa: F401 from spyglass.lfp.lfp_electrode import LFPElectrodeGroup - -# from spyglass.utils.dj_helper_fn import fetch_nwb # dj_replace from spyglass.utils import SpyglassMixin, logger schema = dj.schema("lfp_v1") diff --git a/src/spyglass/linearization/v1/main.py b/src/spyglass/linearization/v1/main.py index ae47477cb..4c135e884 100644 --- a/src/spyglass/linearization/v1/main.py +++ b/src/spyglass/linearization/v1/main.py @@ -173,7 +173,7 @@ def make(self, key): self.insert1(key) - from ..merge import LinearizedPositionOutput + from spyglass.linearization.merge import LinearizedPositionOutput part_name = to_camel_case(self.table_name.split("__")[-1]) diff --git a/src/spyglass/lock/file_lock.py b/src/spyglass/lock/file_lock.py index c20927520..f2207dd20 100644 --- a/src/spyglass/lock/file_lock.py +++ b/src/spyglass/lock/file_lock.py @@ -6,7 +6,7 @@ schema = dj.schema("file_lock") -from ..common.common_nwbfile import AnalysisNwbfile, Nwbfile +from spyglass.common.common_nwbfile import AnalysisNwbfile, Nwbfile @schema diff --git a/src/spyglass/decoding/visualization/__init__.py b/src/spyglass/mua/__init__.py similarity index 100% rename from src/spyglass/decoding/visualization/__init__.py rename to src/spyglass/mua/__init__.py diff --git a/src/spyglass/mua/v1/__init__.py b/src/spyglass/mua/v1/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/src/spyglass/mua/v1/mua.py b/src/spyglass/mua/v1/mua.py new file mode 100644 index 000000000..86c93de2e --- /dev/null +++ b/src/spyglass/mua/v1/mua.py @@ -0,0 +1,112 @@ +import datajoint as dj +import numpy as np +from ripple_detection import multiunit_HSE_detector + +from spyglass.common.common_interval import IntervalList +from spyglass.common.common_nwbfile import AnalysisNwbfile +from spyglass.position import PositionOutput # noqa: F401 +from spyglass.spikesorting.analysis.v1.group import ( + SortedSpikesGroup, +) # noqa: F401 +from spyglass.utils.dj_mixin import SpyglassMixin + +schema = dj.schema("mua_v1") + + +@schema +class MuaEventsParameters(SpyglassMixin, dj.Manual): + """Params to extract times of high mulitunit activity during immobility.""" + + definition = """ + mua_param_name : varchar(80) # a name for this set of parameters + ---- + mua_param_dict : BLOB # dictionary of parameters + """ + contents = [ + { + "mua_param_name": "default", + "mua_param_dict": { + "minimum_duration": 0.015, # seconds + "zscore_threshold": 2.0, + "close_event_threshold": 0.0, # seconds + "speed_threshold": 4.0, # cm/s + }, + }, + ] + + @classmethod + def insert_default(cls): + """Insert the default parameter set""" + cls.insert(cls.contents, skip_duplicates=True) + + +@schema +class MuaEventsV1(SpyglassMixin, dj.Computed): + definition = """ + -> MuaEventsParameters + -> SortedSpikesGroup + -> PositionOutput.proj(pos_merge_id='merge_id') + -> IntervalList.proj(artifact_interval_list_name='interval_list_name') # exclude artifact times + --- + -> AnalysisNwbfile + mua_times_object_id : varchar(40) + """ + + def make(self, key): + # TODO: exclude artifact times + position_info = ( + PositionOutput & {"merge_id": key["pos_merge_id"]} + ).fetch1_dataframe() + speed_name = ( + "speed" if "speed" in position_info.columns else "head_speed" + ) + speed = position_info[speed_name].to_numpy() + time = position_info.index.to_numpy() + + spike_indicator = SortedSpikesGroup.get_spike_indicator(key, time) + spike_indicator = spike_indicator.sum(axis=1, keepdims=True) + + sampling_frequency = 1 / np.median(np.diff(time)) + + mua_params = (MuaEventsParameters & key).fetch1("mua_param_dict") + + # Exclude artifact times + # Alternatively could set to NaN and leave them out of the firing rate calculation + # in the multiunit_HSE_detector function + artifact_key = { + "nwb_file_name": key["nwb_file_name"], + "interval_list_name": key["artifact_interval_list_name"], + } + artifact_times = (IntervalList & artifact_key).fetch1("valid_times") + mean_n_spikes = np.mean(spike_indicator) + for artifact_time in artifact_times: + spike_indicator[ + np.logical_and( + time >= artifact_time.start, time <= artifact_time.stop + ) + ] = mean_n_spikes + + mua_times = multiunit_HSE_detector( + time, spike_indicator, speed, sampling_frequency, **mua_params + ) + # Insert into analysis nwb file + nwb_analysis_file = AnalysisNwbfile() + nwb_file_name = (SortedSpikesGroup & key).fetch1("nwb_file_name") + key["analysis_file_name"] = nwb_analysis_file.create(nwb_file_name) + key["mua_times_object_id"] = nwb_analysis_file.add_nwb_object( + analysis_file_name=key["analysis_file_name"], + nwb_object=mua_times, + ) + nwb_analysis_file.add( + nwb_file_name=nwb_file_name, + analysis_file_name=key["analysis_file_name"], + ) + + self.insert1(key) + + def fetch1_dataframe(self): + """Convenience function for returning the marks in a readable format""" + return self.fetch_dataframe()[0] + + def fetch_dataframe(self): + return [data["mua_times"] for data in self.fetch_nwb()] diff --git a/src/spyglass/position/__init__.py b/src/spyglass/position/__init__.py index dca3dccea..e5d0b797b 100644 --- a/src/spyglass/position/__init__.py +++ b/src/spyglass/position/__init__.py @@ -1 +1 @@ -from .position_merge import PositionOutput +from spyglass.position.position_merge import PositionOutput diff --git a/src/spyglass/position/v1/position_dlc_centroid.py b/src/spyglass/position/v1/position_dlc_centroid.py index 174ca67cd..df2de1544 100644 --- a/src/spyglass/position/v1/position_dlc_centroid.py +++ b/src/spyglass/position/v1/position_dlc_centroid.py @@ -6,10 +6,9 @@ import pynwb from position_tools import get_distance, get_velocity -from ...common.common_behav import RawPosition -from ...common.common_nwbfile import AnalysisNwbfile -from ...utils.dj_mixin import SpyglassMixin -from .dlc_utils import ( +from spyglass.common.common_behav import RawPosition +from spyglass.common.common_nwbfile import AnalysisNwbfile +from spyglass.position.v1.dlc_utils import ( _key_to_smooth_func_dict, get_span_start_stop, interp_pos, @@ -17,8 +16,9 @@ validate_option, validate_smooth_params, ) -from .position_dlc_cohort import DLCSmoothInterpCohort -from .position_dlc_position import DLCSmoothInterpParams +from spyglass.position.v1.position_dlc_cohort import DLCSmoothInterpCohort +from spyglass.position.v1.position_dlc_position import DLCSmoothInterpParams +from spyglass.utils.dj_mixin import SpyglassMixin schema = dj.schema("position_v1_dlc_centroid") diff --git a/src/spyglass/position/v1/position_dlc_cohort.py b/src/spyglass/position/v1/position_dlc_cohort.py index 16a61e748..b265a1ce5 100644 --- a/src/spyglass/position/v1/position_dlc_cohort.py +++ b/src/spyglass/position/v1/position_dlc_cohort.py @@ -2,10 +2,12 @@ import numpy as np import pandas as pd -from ...common.common_nwbfile import AnalysisNwbfile -from ...utils.dj_mixin import SpyglassMixin -from .position_dlc_pose_estimation import DLCPoseEstimation # noqa: F401 -from .position_dlc_position import DLCSmoothInterp +from spyglass.common.common_nwbfile import AnalysisNwbfile +from spyglass.position.v1.position_dlc_pose_estimation import ( # noqa: F401 + DLCPoseEstimation, +) +from spyglass.position.v1.position_dlc_position import DLCSmoothInterp +from spyglass.utils.dj_mixin import SpyglassMixin schema = dj.schema("position_v1_dlc_cohort") diff --git a/src/spyglass/position/v1/position_dlc_orient.py b/src/spyglass/position/v1/position_dlc_orient.py index 9b226d1a0..48f7849be 100644 --- a/src/spyglass/position/v1/position_dlc_orient.py +++ b/src/spyglass/position/v1/position_dlc_orient.py @@ -4,10 +4,11 @@ import pynwb from position_tools.core import gaussian_smooth -from ...common.common_behav import RawPosition -from ...common.common_nwbfile import AnalysisNwbfile -from ...utils.dj_mixin import SpyglassMixin -from .dlc_utils import get_span_start_stop +from spyglass.common.common_behav import RawPosition +from spyglass.common.common_nwbfile import AnalysisNwbfile +from spyglass.position.v1.dlc_utils import get_span_start_stop +from spyglass.utils.dj_mixin import SpyglassMixin + from .position_dlc_cohort import DLCSmoothInterpCohort schema = dj.schema("position_v1_dlc_orient") diff --git a/src/spyglass/position/v1/position_dlc_pose_estimation.py b/src/spyglass/position/v1/position_dlc_pose_estimation.py index 500f888b5..120d292bb 100644 --- a/src/spyglass/position/v1/position_dlc_pose_estimation.py +++ b/src/spyglass/position/v1/position_dlc_pose_estimation.py @@ -1,7 +1,6 @@ import os from datetime import datetime -import cv2 import datajoint as dj import matplotlib.pyplot as plt import numpy as np @@ -9,11 +8,12 @@ import pynwb from IPython.display import display -from ...common.common_behav import ( # noqa: F401 +from spyglass.common.common_behav import ( # noqa: F401 RawPosition, VideoFile, convert_epoch_interval_name_to_position_interval_name, ) + from ...common.common_nwbfile import AnalysisNwbfile from ...utils.dj_mixin import SpyglassMixin from .dlc_utils import OutputLogger, infer_output_dir @@ -49,6 +49,7 @@ def get_video_crop(cls, video_path): crop_ints : list list of 4 integers [x min, x max, y min, y max] """ + import cv2 cap = cv2.VideoCapture(video_path) _, frame = cap.read() diff --git a/src/spyglass/position/v1/position_dlc_position.py b/src/spyglass/position/v1/position_dlc_position.py index 0916115e5..4ca199241 100644 --- a/src/spyglass/position/v1/position_dlc_position.py +++ b/src/spyglass/position/v1/position_dlc_position.py @@ -3,15 +3,16 @@ import pandas as pd import pynwb -from ...common.common_nwbfile import AnalysisNwbfile -from ...utils.dj_mixin import SpyglassMixin -from .dlc_utils import ( +from spyglass.common.common_nwbfile import AnalysisNwbfile +from spyglass.position.v1.dlc_utils import ( _key_to_smooth_func_dict, get_span_start_stop, interp_pos, validate_option, validate_smooth_params, ) +from spyglass.utils.dj_mixin import SpyglassMixin + from .position_dlc_pose_estimation import DLCPoseEstimation schema = dj.schema("position_v1_dlc_position") diff --git a/src/spyglass/position/v1/position_dlc_project.py b/src/spyglass/position/v1/position_dlc_project.py index c0ad0ab30..32615c0a5 100644 --- a/src/spyglass/position/v1/position_dlc_project.py +++ b/src/spyglass/position/v1/position_dlc_project.py @@ -14,11 +14,14 @@ import ruamel.yaml from spyglass.common.common_lab import LabTeam +from spyglass.position.v1.dlc_utils import ( + _set_permissions, + check_videofile, + get_video_path, +) from spyglass.settings import dlc_project_dir, dlc_video_dir from spyglass.utils.dj_mixin import SpyglassMixin -from .dlc_utils import _set_permissions, check_videofile, get_video_path - schema = dj.schema("position_v1_dlc_project") @@ -491,7 +494,7 @@ def import_labeled_frames( f"{import_labeled_data_path.as_posix()}/{video_file}/*.h5" )[0] dlc_df = pd.read_hdf(h5_file) - dlc_df.columns.set_levels([team_name], level=0, inplace=True) + dlc_df.columns = dlc_df.columns.set_levels([team_name], level=0) dlc_df.to_hdf( Path( f"{current_labeled_data_path.as_posix()}/{video_file}/CollectedData_{team_name}.h5" diff --git a/src/spyglass/position/v1/position_dlc_selection.py b/src/spyglass/position/v1/position_dlc_selection.py index 7abc7da8b..50da599f6 100644 --- a/src/spyglass/position/v1/position_dlc_selection.py +++ b/src/spyglass/position/v1/position_dlc_selection.py @@ -7,20 +7,20 @@ import pynwb from datajoint.utils import to_camel_case -from ...common.common_behav import ( +from spyglass.common.common_behav import ( convert_epoch_interval_name_to_position_interval_name, ) -from ...common.common_nwbfile import AnalysisNwbfile -from ...utils.dj_mixin import SpyglassMixin -from .dlc_utils import get_video_path, make_video -from .position_dlc_centroid import DLCCentroid -from .position_dlc_cohort import DLCSmoothInterpCohort -from .position_dlc_orient import DLCOrientation -from .position_dlc_pose_estimation import ( +from spyglass.common.common_nwbfile import AnalysisNwbfile +from spyglass.position.v1.dlc_utils import make_video +from spyglass.position.v1.position_dlc_centroid import DLCCentroid +from spyglass.position.v1.position_dlc_cohort import DLCSmoothInterpCohort +from spyglass.position.v1.position_dlc_orient import DLCOrientation +from spyglass.position.v1.position_dlc_pose_estimation import ( DLCPoseEstimation, DLCPoseEstimationSelection, ) -from .position_dlc_position import DLCSmoothInterpParams +from spyglass.position.v1.position_dlc_position import DLCSmoothInterpParams +from spyglass.utils.dj_mixin import SpyglassMixin schema = dj.schema("position_v1_dlc_selection") diff --git a/src/spyglass/position/v1/position_dlc_training.py b/src/spyglass/position/v1/position_dlc_training.py index 125672a95..ec40d43e0 100644 --- a/src/spyglass/position/v1/position_dlc_training.py +++ b/src/spyglass/position/v1/position_dlc_training.py @@ -4,11 +4,10 @@ import datajoint as dj +from spyglass.position.v1.dlc_utils import OutputLogger +from spyglass.position.v1.position_dlc_project import DLCProject from spyglass.utils.dj_mixin import SpyglassMixin -from .dlc_utils import OutputLogger -from .position_dlc_project import DLCProject - schema = dj.schema("position_v1_dlc_training") diff --git a/src/spyglass/position/v1/position_trodes_position.py b/src/spyglass/position/v1/position_trodes_position.py index 859e6ad6e..211c629f4 100644 --- a/src/spyglass/position/v1/position_trodes_position.py +++ b/src/spyglass/position/v1/position_trodes_position.py @@ -8,12 +8,12 @@ from datajoint.utils import to_camel_case from tqdm import tqdm as tqdm -from ...common.common_behav import RawPosition -from ...common.common_nwbfile import AnalysisNwbfile -from ...common.common_position import IntervalPositionInfo -from ...utils import logger -from ...utils.dj_mixin import SpyglassMixin -from .dlc_utils import check_videofile, get_video_path +from spyglass.common.common_behav import RawPosition +from spyglass.common.common_nwbfile import AnalysisNwbfile +from spyglass.common.common_position import IntervalPositionInfo +from spyglass.position.v1.dlc_utils import check_videofile, get_video_path +from spyglass.utils import logger +from spyglass.utils.dj_mixin import SpyglassMixin schema = dj.schema("position_v1_trodes_position") diff --git a/src/spyglass/ripple/v1/__init__.py b/src/spyglass/ripple/v1/__init__.py index e6d0de6cc..888624332 100644 --- a/src/spyglass/ripple/v1/__init__.py +++ b/src/spyglass/ripple/v1/__init__.py @@ -1,5 +1,5 @@ from spyglass.ripple.v1.ripple import ( - RippleParameters, RippleLFPSelection, + RippleParameters, RippleTimesV1, ) diff --git a/src/spyglass/ripple/v1/ripple.py b/src/spyglass/ripple/v1/ripple.py index 4d2397bc3..38618f301 100644 --- a/src/spyglass/ripple/v1/ripple.py +++ b/src/spyglass/ripple/v1/ripple.py @@ -149,7 +149,6 @@ class RippleTimesV1(SpyglassMixin, dj.Computed): -> RippleLFPSelection -> RippleParameters -> PositionOutput.proj(pos_merge_id='merge_id') - --- -> AnalysisNwbfile ripple_times_object_id : varchar(40) diff --git a/src/spyglass/sharing/__init__.py b/src/spyglass/sharing/__init__.py index 4a34a113b..e84a02cb6 100644 --- a/src/spyglass/sharing/__init__.py +++ b/src/spyglass/sharing/__init__.py @@ -1,4 +1,4 @@ -from .sharing_kachery import ( +from spyglass.sharing.sharing_kachery import ( AnalysisNwbfileKachery, AnalysisNwbfileKacherySelection, KacheryZone, diff --git a/src/spyglass/sharing/sharing_kachery.py b/src/spyglass/sharing/sharing_kachery.py index 5aa4ebe56..8844aad4b 100644 --- a/src/spyglass/sharing/sharing_kachery.py +++ b/src/spyglass/sharing/sharing_kachery.py @@ -4,12 +4,11 @@ import kachery_cloud as kcl from datajoint.errors import DataJointError +from spyglass.common.common_lab import Lab # noqa: F401 +from spyglass.common.common_nwbfile import AnalysisNwbfile from spyglass.settings import config from spyglass.utils import SpyglassMixin, logger -from ..common.common_lab import Lab # noqa: F401 -from ..common.common_nwbfile import AnalysisNwbfile - # define the environment variable name for the kachery zone and the cloud directory kachery_zone_envar = "KACHERY_ZONE" kachery_cloud_dir_envar = "KACHERY_CLOUD_DIR" diff --git a/src/spyglass/spikesorting/__init__.py b/src/spyglass/spikesorting/__init__.py index f7f59d58f..e69de29bb 100644 --- a/src/spyglass/spikesorting/__init__.py +++ b/src/spyglass/spikesorting/__init__.py @@ -1,40 +0,0 @@ -from .curation_figurl import CurationFigurl, CurationFigurlSelection -from .imported import ImportedSpikeSorting -from .sortingview import SortingviewWorkspace, SortingviewWorkspaceSelection -from .spikesorting_artifact import ( - ArtifactDetection, - ArtifactDetectionParameters, - ArtifactDetectionSelection, - ArtifactRemovedIntervalList, -) -from .spikesorting_curation import ( - AutomaticCuration, - AutomaticCurationParameters, - AutomaticCurationSelection, - CuratedSpikeSorting, - CuratedSpikeSortingSelection, - Curation, - MetricParameters, - MetricSelection, - QualityMetrics, - UnitInclusionParameters, - WaveformParameters, - Waveforms, - WaveformSelection, -) -from .spikesorting_populator import ( - SpikeSortingPipelineParameters, - spikesorting_pipeline_populator, -) -from .spikesorting_recording import ( - SortGroup, - SortInterval, - SpikeSortingPreprocessingParameters, - SpikeSortingRecording, - SpikeSortingRecordingSelection, -) -from .spikesorting_sorting import ( - SpikeSorterParameters, - SpikeSorting, - SpikeSortingSelection, -) diff --git a/src/spyglass/spikesorting/analysis/__init__.py b/src/spyglass/spikesorting/analysis/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/src/spyglass/spikesorting/analysis/v1/__init__.py b/src/spyglass/spikesorting/analysis/v1/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/src/spyglass/spikesorting/analysis/v1/group.py b/src/spyglass/spikesorting/analysis/v1/group.py new file mode 100644 index 000000000..0f52fdd0e --- /dev/null +++ b/src/spyglass/spikesorting/analysis/v1/group.py @@ -0,0 +1,205 @@ +from itertools import compress + +import datajoint as dj +import numpy as np +from ripple_detection import get_multiunit_population_firing_rate + +from spyglass.common import Session # noqa: F401 +from spyglass.spikesorting.spikesorting_merge import SpikeSortingOutput +from spyglass.utils.dj_mixin import SpyglassMixin + +schema = dj.schema("spikesorting_group_v1") + + +@schema +class UnitSelectionParams(SpyglassMixin, dj.Manual): + definition = """ + unit_filter_params_name: varchar(128) + --- + include_labels = Null: longblob + exclude_labels = Null: longblob + """ + contents = [ + [ + "all_units", + [], + [], + ], + [ + "exclude_noise", + [], + ["noise", "mua"], + ], + [ + "default_exclusion", + [], + ["noise", "mua"], + ], + ] + + @classmethod + def insert_default(cls): + cls.insert(cls.contents, skip_duplicates=True) + + +@schema +class SortedSpikesGroup(SpyglassMixin, dj.Manual): + definition = """ + -> Session + -> UnitSelectionParams + sorted_spikes_group_name: varchar(80) + """ + + class SortGroup(SpyglassMixin, dj.Part): + definition = """ + -> master + -> SpikeSortingOutput.proj(spikesorting_merge_id='merge_id') + """ + + def create_group( + self, + group_name: str, + nwb_file_name: str, + unit_filter_params_name: str = "all_units", + keys: list[dict] = [], + ): + group_key = { + "sorted_spikes_group_name": group_name, + "nwb_file_name": nwb_file_name, + "unit_filter_params_name": unit_filter_params_name, + } + parts_insert = [{**key, **group_key} for key in keys] + + self.insert1( + group_key, + skip_duplicates=True, + ) + self.SortGroup.insert(parts_insert) + + @staticmethod + def filter_units( + labels: list[list[str]], + include_labels: list[str], + exclude_labels: list[str], + ) -> np.ndarray: + """ + Filter units based on labels + """ + include_labels = np.unique(include_labels) + exclude_labels = np.unique(exclude_labels) + + include_mask = np.zeros(len(labels), dtype=bool) + for ind, unit_labels in enumerate(labels): + if isinstance(unit_labels, str): + unit_labels = [unit_labels] + if ( + include_labels + and not np.isin(include_labels, unit_labels).any() + ): + continue + if np.isin(exclude_labels, unit_labels).any(): + continue + include_mask[ind] = True + return include_mask + + @staticmethod + def fetch_spike_data(key, time_slice=None): + # get merge_ids for SpikeSortingOutput + merge_ids = ( + ( + SortedSpikesGroup.SortGroup + & { + "nwb_file_name": key["nwb_file_name"], + "sorted_spikes_group_name": key["sorted_spikes_group_name"], + } + ) + ).fetch("spikesorting_merge_id") + + # get the filtering parameters + include_labels, exclude_labels = (UnitSelectionParams & key).fetch1( + "include_labels", "exclude_labels" + ) + + # get the spike times for each merge_id + spike_times = [] + for merge_id in merge_ids: + nwb_file = SpikeSortingOutput().fetch_nwb({"merge_id": merge_id})[0] + nwb_field_name = ( + "object_id" + if "object_id" in nwb_file + else "units" if "units" in nwb_file else None + ) + if nwb_field_name is None: + # case where no units found or curation removed all units + continue + sorting_spike_times = nwb_file[nwb_field_name][ + "spike_times" + ].to_list() + + # filter the spike times based on the labels if present + if "label" in nwb_file[nwb_field_name]: + group_label_list = nwb_file[nwb_field_name]["label"].to_list() + include_unit = SortedSpikesGroup.filter_units( + group_label_list, include_labels, exclude_labels + ) + + sorting_spike_times = list( + compress(sorting_spike_times, include_unit) + ) + + # filter the spike times based on the time slice if provided + if time_slice is not None: + sorting_spike_times = [ + times[ + np.logical_and( + times >= time_slice.start, times <= time_slice.stop + ) + ] + for times in sorting_spike_times + ] + + # append the approved spike times to the list + spike_times.extend(sorting_spike_times) + + return spike_times + + @classmethod + def get_spike_indicator(cls, key: dict, time: np.ndarray) -> np.ndarray: + time = np.asarray(time) + min_time, max_time = time[[0, -1]] + spike_times = cls.fetch_spike_data(key) + spike_indicator = np.zeros((len(time), len(spike_times))) + + for ind, times in enumerate(spike_times): + times = times[np.logical_and(times >= min_time, times <= max_time)] + spike_indicator[:, ind] = np.bincount( + np.digitize(times, time[1:-1]), + minlength=time.shape[0], + ) + + if spike_indicator.ndim == 1: + spike_indicator = spike_indicator[:, np.newaxis] + + return spike_indicator + + @classmethod + def get_firing_rate( + cls, key: dict, time: np.ndarray, multiunit: bool = False + ) -> np.ndarray: + spike_indicator = cls.get_spike_indicator(key, time) + if spike_indicator.ndim == 1: + spike_indicator = spike_indicator[:, np.newaxis] + + sampling_frequency = 1 / np.median(np.diff(time)) + + if multiunit: + spike_indicator = spike_indicator.sum(axis=1, keepdims=True) + return np.stack( + [ + get_multiunit_population_firing_rate( + indicator[:, np.newaxis], sampling_frequency + ) + for indicator in spike_indicator.T + ], + axis=1, + ) diff --git a/src/spyglass/spikesorting/figurl_views/__init__.py b/src/spyglass/spikesorting/figurl_views/__init__.py deleted file mode 100644 index ce2ea5469..000000000 --- a/src/spyglass/spikesorting/figurl_views/__init__.py +++ /dev/null @@ -1,2 +0,0 @@ -from .SpikeSortingRecordingView import SpikeSortingRecordingView -from .SpikeSortingView import SpikeSortingView diff --git a/src/spyglass/spikesorting/imported.py b/src/spyglass/spikesorting/imported.py index bb2fb2fd0..ca1bdc9d0 100644 --- a/src/spyglass/spikesorting/imported.py +++ b/src/spyglass/spikesorting/imported.py @@ -1,8 +1,8 @@ import copy import datajoint as dj +import pandas as pd import pynwb -from datajoint.utils import to_camel_case from spyglass.common.common_nwbfile import Nwbfile from spyglass.common.common_session import Session # noqa: F401 @@ -21,8 +21,18 @@ class ImportedSpikeSorting(SpyglassMixin, dj.Imported): _nwb_table = Nwbfile + class Annotations(SpyglassMixin, dj.Part): + definition = """ + -> ImportedSpikeSorting + id: int # unit id, corresponds to dataframe index of unit in NWB file + --- + label = Null: longblob # list of string labels for the unit + annotations: longblob # dict of other annotations (e.g. metrics) + """ + def make(self, key): orig_key = copy.deepcopy(key) + nwb_file_abs_path = Nwbfile.get_abs_path(key["nwb_file_name"]) with pynwb.NWBHDF5IO( @@ -33,11 +43,15 @@ def make(self, key): logger.warn("No units found in NWB file") return - from spyglass.spikesorting.merge import SpikeSortingOutput # noqa: F401 + from spyglass.spikesorting.spikesorting_merge import ( # noqa: F401 + SpikeSortingOutput, + ) key["object_id"] = nwbfile.units.object_id - part_name = SpikeSortingOutput._part_name(self.table_name) + self.insert1(key, skip_duplicates=True) + + part_name = SpikeSortingOutput._part_name(self.table_name) SpikeSortingOutput._merge_insert( [orig_key], part_name=part_name, skip_duplicates=True ) @@ -53,3 +67,79 @@ def get_sorting(cls, key): raise NotImplementedError( "Imported spike sorting does not have a `get_sorting` method" ) + + def add_annotation( + self, key, id, label=[], annotations={}, merge_annotations=False + ): + """Manually add annotations to the spike sorting output + + Parameters + ---------- + key : dict + restriction key for ImportedSpikeSorting + id : int + unit id + label : List[str], optional + list of str labels for the unit, by default None + annotations : dict, optional + dictionary of other annotation values for unit, by default None + merge_annotations : bool, optional + whether to merge with existing annotations, by default False + """ + if isinstance(label, str): + label = [label] + query = self & key + if not len(query) == 1: + raise ValueError( + f"ImportedSpikeSorting key must be unique. Found: {query}" + ) + unit_key = {**key, "id": id} + annotation_query = ImportedSpikeSorting.Annotations & unit_key + if annotation_query and not merge_annotations: + raise ValueError( + f"Unit already has annotations: {annotation_query}" + ) + elif annotation_query: + existing_annotations = annotation_query.fetch1() + existing_annotations["label"] += label + existing_annotations["annotations"].update(annotations) + self.Annotations.update1(existing_annotations) + else: + self.Annotations.insert1( + dict(unit_key, label=label, annotations=annotations), + skip_duplicates=True, + ) + + def make_df_from_annotations(self): + """Convert the annotations part table into a dataframe that can be + concatenated to the spikes dataframe in the nwb file.""" + df = [] + for id, label, annotations in zip( + *self.Annotations.fetch("id", "label", "annotations") + ): + df.append( + dict( + id=id, + label=label, + **annotations, + ) + ) + df = pd.DataFrame(df) + df.set_index("id", inplace=True) + return df + + def fetch_nwb(self, *attrs, **kwargs): + """class method to fetch the nwb and add annotations to the spike dfs returned""" + # get the original nwbs + nwbs = super().fetch_nwb(*attrs, **kwargs) + # for each nwb, get the annotations and add them to the spikes dataframe + for i, key in enumerate(self.fetch("KEY")): + if not ImportedSpikeSorting.Annotations & key: + continue + # make the annotation_df + annotation_df = (self & key).make_df_from_annotations() + # concatenate the annotations to the spikes dataframe in the returned nwb + nwbs[i]["object_id"] = pd.concat( + [nwbs[i]["object_id"], annotation_df], axis="columns" + ) + return nwbs diff --git a/src/spyglass/spikesorting/merge.py b/src/spyglass/spikesorting/spikesorting_merge.py similarity index 96% rename from src/spyglass/spikesorting/merge.py rename to src/spyglass/spikesorting/spikesorting_merge.py index db8893040..b59a48911 100644 --- a/src/spyglass/spikesorting/merge.py +++ b/src/spyglass/spikesorting/spikesorting_merge.py @@ -4,7 +4,7 @@ from ripple_detection import get_multiunit_population_firing_rate from spyglass.spikesorting.imported import ImportedSpikeSorting # noqa: F401 -from spyglass.spikesorting.spikesorting_curation import ( # noqa: F401 +from spyglass.spikesorting.v0.spikesorting_curation import ( # noqa: F401 CuratedSpikeSorting, ) from spyglass.spikesorting.v1.curation import CurationV1 # noqa: F401 @@ -81,7 +81,7 @@ def get_spike_times(cls, key): def get_spike_indicator(cls, key, time): time = np.asarray(time) min_time, max_time = time[[0, -1]] - spike_times = cls.load_spike_data(key) + spike_times = cls.fetch_spike_data(key) spike_indicator = np.zeros((len(time), len(spike_times))) for ind, times in enumerate(spike_times): diff --git a/src/spyglass/spikesorting/v0/__init__.py b/src/spyglass/spikesorting/v0/__init__.py new file mode 100644 index 000000000..f15d25230 --- /dev/null +++ b/src/spyglass/spikesorting/v0/__init__.py @@ -0,0 +1,45 @@ +from spyglass.spikesorting.v0.curation_figurl import ( # noqa: F401 + CurationFigurl, + CurationFigurlSelection, +) +from spyglass.spikesorting.v0.sortingview import ( # noqa: F401 + SortingviewWorkspace, + SortingviewWorkspaceSelection, +) +from spyglass.spikesorting.v0.spikesorting_artifact import ( # noqa: F401 + ArtifactDetection, + ArtifactDetectionParameters, + ArtifactDetectionSelection, + ArtifactRemovedIntervalList, +) +from spyglass.spikesorting.v0.spikesorting_curation import ( # noqa: F401 + AutomaticCuration, + AutomaticCurationParameters, + AutomaticCurationSelection, + CuratedSpikeSorting, + CuratedSpikeSortingSelection, + Curation, + MetricParameters, + MetricSelection, + QualityMetrics, + UnitInclusionParameters, + WaveformParameters, + Waveforms, + WaveformSelection, +) +from spyglass.spikesorting.v0.spikesorting_populator import ( # noqa: F401 + SpikeSortingPipelineParameters, + spikesorting_pipeline_populator, +) +from spyglass.spikesorting.v0.spikesorting_recording import ( # noqa: F401 + SortGroup, + SortInterval, + SpikeSortingPreprocessingParameters, + SpikeSortingRecording, + SpikeSortingRecordingSelection, +) +from spyglass.spikesorting.v0.spikesorting_sorting import ( # noqa: F401 + SpikeSorterParameters, + SpikeSorting, + SpikeSortingSelection, +) diff --git a/src/spyglass/spikesorting/curation_figurl.py b/src/spyglass/spikesorting/v0/curation_figurl.py similarity index 96% rename from src/spyglass/spikesorting/curation_figurl.py rename to src/spyglass/spikesorting/v0/curation_figurl.py index 8ba0d3cfb..caab594b7 100644 --- a/src/spyglass/spikesorting/curation_figurl.py +++ b/src/spyglass/spikesorting/v0/curation_figurl.py @@ -6,9 +6,11 @@ import spikeinterface as si from sortingview.SpikeSortingView import SpikeSortingView -from spyglass.spikesorting.spikesorting_curation import Curation -from spyglass.spikesorting.spikesorting_recording import SpikeSortingRecording -from spyglass.spikesorting.spikesorting_sorting import SpikeSorting +from spyglass.spikesorting.v0.spikesorting_curation import Curation +from spyglass.spikesorting.v0.spikesorting_recording import ( + SpikeSortingRecording, +) +from spyglass.spikesorting.v0.spikesorting_sorting import SpikeSorting from spyglass.utils import SpyglassMixin, logger schema = dj.schema("spikesorting_curation_figurl") diff --git a/src/spyglass/spikesorting/figurl_views/SpikeSortingRecordingView.py b/src/spyglass/spikesorting/v0/figurl_views/SpikeSortingRecordingView.py similarity index 97% rename from src/spyglass/spikesorting/figurl_views/SpikeSortingRecordingView.py rename to src/spyglass/spikesorting/v0/figurl_views/SpikeSortingRecordingView.py index 5fe0f9df5..0c0e4a9e1 100644 --- a/src/spyglass/spikesorting/figurl_views/SpikeSortingRecordingView.py +++ b/src/spyglass/spikesorting/v0/figurl_views/SpikeSortingRecordingView.py @@ -8,7 +8,9 @@ from sortingview.SpikeSortingView import create_raw_traces_plot from sortingview.SpikeSortingView.Figure import Figure -from spyglass.spikesorting.spikesorting_recording import SpikeSortingRecording +from spyglass.spikesorting.v0.spikesorting_recording import ( + SpikeSortingRecording, +) from spyglass.utils import SpyglassMixin, logger schema = dj.schema("figurl_view_spike_sorting_recording") diff --git a/src/spyglass/spikesorting/figurl_views/SpikeSortingView.py b/src/spyglass/spikesorting/v0/figurl_views/SpikeSortingView.py similarity index 94% rename from src/spyglass/spikesorting/figurl_views/SpikeSortingView.py rename to src/spyglass/spikesorting/v0/figurl_views/SpikeSortingView.py index b96fd0f96..d05b61f1a 100644 --- a/src/spyglass/spikesorting/figurl_views/SpikeSortingView.py +++ b/src/spyglass/spikesorting/v0/figurl_views/SpikeSortingView.py @@ -5,11 +5,12 @@ SpikeSortingView as SortingViewSpikeSortingView, ) +from spyglass.spikesorting.v0 import SpikeSorting, SpikeSortingRecording +from spyglass.spikesorting.v0.figurl_views.prepare_spikesortingview_data import ( + prepare_spikesortingview_data, +) from spyglass.utils import SpyglassMixin, logger -from ..spikesorting import SpikeSorting, SpikeSortingRecording -from .prepare_spikesortingview_data import prepare_spikesortingview_data - schema = dj.schema("figurl_view_spike_sorting_recording") diff --git a/src/spyglass/spikesorting/v0/figurl_views/__init__.py b/src/spyglass/spikesorting/v0/figurl_views/__init__.py new file mode 100644 index 000000000..aae78f7c0 --- /dev/null +++ b/src/spyglass/spikesorting/v0/figurl_views/__init__.py @@ -0,0 +1,6 @@ +from spyglass.spikesorting.v0.figurl_views.SpikeSortingRecordingView import ( + SpikeSortingRecordingView, +) +from spyglass.spikesorting.v0.figurl_views.SpikeSortingView import ( + SpikeSortingView, +) diff --git a/src/spyglass/spikesorting/figurl_views/prepare_spikesortingview_data.py b/src/spyglass/spikesorting/v0/figurl_views/prepare_spikesortingview_data.py similarity index 100% rename from src/spyglass/spikesorting/figurl_views/prepare_spikesortingview_data.py rename to src/spyglass/spikesorting/v0/figurl_views/prepare_spikesortingview_data.py diff --git a/src/spyglass/spikesorting/merged_sorting_extractor.py b/src/spyglass/spikesorting/v0/merged_sorting_extractor.py similarity index 100% rename from src/spyglass/spikesorting/merged_sorting_extractor.py rename to src/spyglass/spikesorting/v0/merged_sorting_extractor.py diff --git a/src/spyglass/spikesorting/sortingview.py b/src/spyglass/spikesorting/v0/sortingview.py similarity index 96% rename from src/spyglass/spikesorting/sortingview.py rename to src/spyglass/spikesorting/v0/sortingview.py index 73a6fb1cf..b9e3529be 100644 --- a/src/spyglass/spikesorting/sortingview.py +++ b/src/spyglass/spikesorting/v0/sortingview.py @@ -2,13 +2,15 @@ import sortingview as sv from spyglass.common.common_lab import LabMember, LabTeam -from spyglass.spikesorting.sortingview_helper_fn import ( +from spyglass.spikesorting.v0.sortingview_helper_fn import ( _create_spikesortingview_workspace, _generate_url, ) -from spyglass.spikesorting.spikesorting_curation import Curation -from spyglass.spikesorting.spikesorting_recording import SpikeSortingRecording -from spyglass.spikesorting.spikesorting_sorting import SpikeSorting +from spyglass.spikesorting.v0.spikesorting_curation import Curation +from spyglass.spikesorting.v0.spikesorting_recording import ( + SpikeSortingRecording, +) +from spyglass.spikesorting.v0.spikesorting_sorting import SpikeSorting from spyglass.utils import SpyglassMixin, logger schema = dj.schema("spikesorting_sortingview") diff --git a/src/spyglass/spikesorting/sortingview_helper_fn.py b/src/spyglass/spikesorting/v0/sortingview_helper_fn.py similarity index 98% rename from src/spyglass/spikesorting/sortingview_helper_fn.py rename to src/spyglass/spikesorting/v0/sortingview_helper_fn.py index 735f462bf..431d99e88 100644 --- a/src/spyglass/spikesorting/sortingview_helper_fn.py +++ b/src/spyglass/spikesorting/v0/sortingview_helper_fn.py @@ -8,7 +8,7 @@ import spikeinterface as si from sortingview.SpikeSortingView import SpikeSortingView -from spyglass.spikesorting.merged_sorting_extractor import ( +from spyglass.spikesorting.v0.merged_sorting_extractor import ( MergedSortingExtractor, ) from spyglass.utils import logger diff --git a/src/spyglass/spikesorting/spikesorting_artifact.py b/src/spyglass/spikesorting/v0/spikesorting_artifact.py similarity index 99% rename from src/spyglass/spikesorting/spikesorting_artifact.py rename to src/spyglass/spikesorting/v0/spikesorting_artifact.py index 129893e10..3afae293f 100644 --- a/src/spyglass/spikesorting/spikesorting_artifact.py +++ b/src/spyglass/spikesorting/v0/spikesorting_artifact.py @@ -14,7 +14,9 @@ interval_from_inds, interval_set_difference_inds, ) -from spyglass.spikesorting.spikesorting_recording import SpikeSortingRecording +from spyglass.spikesorting.v0.spikesorting_recording import ( + SpikeSortingRecording, +) from spyglass.utils import SpyglassMixin, logger from spyglass.utils.nwb_helper_fn import get_valid_intervals diff --git a/src/spyglass/spikesorting/spikesorting_curation.py b/src/spyglass/spikesorting/v0/spikesorting_curation.py similarity index 99% rename from src/spyglass/spikesorting/spikesorting_curation.py rename to src/spyglass/spikesorting/v0/spikesorting_curation.py index 69a5ebece..6538b463f 100644 --- a/src/spyglass/spikesorting/spikesorting_curation.py +++ b/src/spyglass/spikesorting/v0/spikesorting_curation.py @@ -16,10 +16,15 @@ from spyglass.common.common_interval import IntervalList from spyglass.common.common_nwbfile import AnalysisNwbfile from spyglass.settings import waveform_dir +from spyglass.spikesorting.v0.merged_sorting_extractor import ( + MergedSortingExtractor, +) +from spyglass.spikesorting.v0.spikesorting_recording import ( + SortInterval, + SpikeSortingRecording, +) from spyglass.utils import SpyglassMixin, logger -from .merged_sorting_extractor import MergedSortingExtractor -from .spikesorting_recording import SortInterval, SpikeSortingRecording from .spikesorting_sorting import SpikeSorting schema = dj.schema("spikesorting_curation") diff --git a/src/spyglass/spikesorting/spikesorting_populator.py b/src/spyglass/spikesorting/v0/spikesorting_populator.py similarity index 97% rename from src/spyglass/spikesorting/spikesorting_populator.py rename to src/spyglass/spikesorting/v0/spikesorting_populator.py index 8db6ee37b..a099ac167 100644 --- a/src/spyglass/spikesorting/spikesorting_populator.py +++ b/src/spyglass/spikesorting/v0/spikesorting_populator.py @@ -1,16 +1,16 @@ import datajoint as dj from spyglass.common import ElectrodeGroup, IntervalList -from spyglass.spikesorting.curation_figurl import ( +from spyglass.spikesorting.v0.curation_figurl import ( CurationFigurl, CurationFigurlSelection, ) -from spyglass.spikesorting.spikesorting_artifact import ( +from spyglass.spikesorting.v0.spikesorting_artifact import ( ArtifactDetection, ArtifactDetectionSelection, ArtifactRemovedIntervalList, ) -from spyglass.spikesorting.spikesorting_curation import ( +from spyglass.spikesorting.v0.spikesorting_curation import ( AutomaticCuration, AutomaticCurationSelection, CuratedSpikeSorting, @@ -21,13 +21,13 @@ Waveforms, WaveformSelection, ) -from spyglass.spikesorting.spikesorting_recording import ( +from spyglass.spikesorting.v0.spikesorting_recording import ( SortGroup, SortInterval, SpikeSortingRecording, SpikeSortingRecordingSelection, ) -from spyglass.spikesorting.spikesorting_sorting import ( +from spyglass.spikesorting.v0.spikesorting_sorting import ( SpikeSorting, SpikeSortingSelection, ) diff --git a/src/spyglass/spikesorting/spikesorting_recording.py b/src/spyglass/spikesorting/v0/spikesorting_recording.py similarity index 100% rename from src/spyglass/spikesorting/spikesorting_recording.py rename to src/spyglass/spikesorting/v0/spikesorting_recording.py diff --git a/src/spyglass/spikesorting/spikesorting_sorting.py b/src/spyglass/spikesorting/v0/spikesorting_sorting.py similarity index 98% rename from src/spyglass/spikesorting/spikesorting_sorting.py rename to src/spyglass/spikesorting/v0/spikesorting_sorting.py index dc431f174..7e4743b93 100644 --- a/src/spyglass/spikesorting/spikesorting_sorting.py +++ b/src/spyglass/spikesorting/v0/spikesorting_sorting.py @@ -14,10 +14,10 @@ from spyglass.common.common_lab import LabMember, LabTeam from spyglass.settings import sorting_dir, temp_dir -from spyglass.spikesorting.spikesorting_artifact import ( +from spyglass.spikesorting.v0.spikesorting_artifact import ( ArtifactRemovedIntervalList, ) -from spyglass.spikesorting.spikesorting_recording import ( +from spyglass.spikesorting.v0.spikesorting_recording import ( SpikeSortingRecording, SpikeSortingRecordingSelection, ) diff --git a/src/spyglass/spikesorting/v1/__init__.py b/src/spyglass/spikesorting/v1/__init__.py index dbe8a5f7d..a2f3ca592 100644 --- a/src/spyglass/spikesorting/v1/__init__.py +++ b/src/spyglass/spikesorting/v1/__init__.py @@ -1,22 +1,29 @@ -from ..imported import ImportedSpikeSorting -from .artifact import ( +from spyglass.spikesorting.imported import ImportedSpikeSorting +from spyglass.spikesorting.v1.artifact import ( ArtifactDetection, ArtifactDetectionParameters, ArtifactDetectionSelection, ) -from .curation import CurationV1 -from .figurl_curation import FigURLCuration, FigURLCurationSelection -from .metric_curation import ( +from spyglass.spikesorting.v1.curation import CurationV1 +from spyglass.spikesorting.v1.figurl_curation import ( + FigURLCuration, + FigURLCurationSelection, +) +from spyglass.spikesorting.v1.metric_curation import ( MetricCuration, MetricCurationParameters, MetricCurationSelection, MetricParameters, WaveformParameters, ) -from .recording import ( +from spyglass.spikesorting.v1.recording import ( SortGroup, SpikeSortingPreprocessingParameters, SpikeSortingRecording, SpikeSortingRecordingSelection, ) -from .sorting import SpikeSorterParameters, SpikeSorting, SpikeSortingSelection +from spyglass.spikesorting.v1.sorting import ( + SpikeSorterParameters, + SpikeSorting, + SpikeSortingSelection, +) diff --git a/src/spyglass/spikesorting/v1/metric_utils.py b/src/spyglass/spikesorting/v1/metric_utils.py index ab440c3d9..f88a1506a 100644 --- a/src/spyglass/spikesorting/v1/metric_utils.py +++ b/src/spyglass/spikesorting/v1/metric_utils.py @@ -1,6 +1,6 @@ +import numpy as np import spikeinterface as si import spikeinterface.qualitymetrics as sq -import numpy as np def compute_isi_violation_fractions( diff --git a/src/spyglass/spikesorting/v1/utils.py b/src/spyglass/spikesorting/v1/utils.py index eaff64739..6a511c43e 100644 --- a/src/spyglass/spikesorting/v1/utils.py +++ b/src/spyglass/spikesorting/v1/utils.py @@ -2,7 +2,7 @@ import numpy as np -from spyglass.spikesorting.merge import SpikeSortingOutput +from spyglass.spikesorting.spikesorting_merge import SpikeSortingOutput from spyglass.spikesorting.v1.artifact import ArtifactDetectionSelection from spyglass.spikesorting.v1.curation import CurationV1 from spyglass.spikesorting.v1.recording import SpikeSortingRecordingSelection diff --git a/src/spyglass/utils/database_settings.py b/src/spyglass/utils/database_settings.py index da65914fa..7fd1b44ff 100755 --- a/src/spyglass/utils/database_settings.py +++ b/src/spyglass/utils/database_settings.py @@ -23,6 +23,7 @@ "ripple", "lfp", "waveform", + "mua", ] diff --git a/tests/conftest.py b/tests/conftest.py index 60df55b3d..e992de345 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -245,7 +245,9 @@ def mini_closed(mini_path): def mini_insert(mini_path, teardown, server, dj_conn): from spyglass.common import LabMember, Nwbfile, Session # noqa: E402 from spyglass.data_import import insert_sessions # noqa: E402 - from spyglass.spikesorting.merge import SpikeSortingOutput # noqa: E402 + from spyglass.spikesorting.spikesorting_merge import ( # noqa: E402 + SpikeSortingOutput, + ) from spyglass.utils.nwb_helper_fn import close_nwb_files # noqa: E402 LabMember().insert1(