Skip to content

Commit e9b9760

Browse files
authored
Merge branch 'main' into add_how_to_make_a_release_notes
2 parents 30c2386 + f4b908c commit e9b9760

90 files changed

Lines changed: 3129 additions & 1039 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/scripts/determine_testing_environment.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@
4848
elif changed_file.name == "nwbextractors.py":
4949
extractors_changed = True # There are NWB tests that are not streaming
5050
stream_extractors_changed = True
51-
elif changed_file.name == "iblextractors.py":
51+
elif changed_file.name == "iblextractors.py" or changed_file.name == "test_iblextractors.py":
5252
stream_extractors_changed = True
5353
elif "core" in changed_file.parts:
5454
core_changed = True

doc/api.rst

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,9 @@ Non-NEO-based
143143
.. autofunction:: read_mcsh5
144144
.. autofunction:: read_mda_recording
145145
.. autofunction:: read_mda_sorting
146-
.. autofunction:: read_nwb
146+
.. autofunction:: read_nwb_sorting
147+
.. autofunction:: read_nwb_recording
148+
.. autofunction:: read_nwb_timeseries
147149
.. autofunction:: read_phy
148150
.. autofunction:: read_shybrid_recording
149151
.. autofunction:: read_shybrid_sorting

doc/how_to/customize_a_plot.rst

Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
Customize a plot
2+
================
3+
4+
The ``SpikeInterface`` widgets are designed to have reasonable default
5+
plotting options, but sometimes you’ll want to make adjustments to the
6+
plots. The plotting functions all return a ``Widget`` object. These
7+
contain and give you access to the underlying matplotlib figure and
8+
axis, which you can apply any matplotlib machinery to. Let’s see how to
9+
do this in an example, by first making some synthetic data and computing
10+
extensions which can be used for plotting.
11+
12+
.. code::
13+
14+
import spikeinterface.full as si
15+
import matplotlib.pyplot as plt
16+
17+
recording, sorting = si.generate_ground_truth_recording(seed=1205)
18+
sorting_analyzer = si.create_sorting_analyzer(sorting=sorting, recording=recording)
19+
sorting_analyzer.compute({"random_spikes": {'seed': 1205}, "templates": {}, "unit_locations": {}})
20+
21+
unit_locations = sorting_analyzer.get_extension("unit_locations").get_data()
22+
23+
24+
25+
.. parsed-literal::
26+
27+
estimate_sparsity (no parallelization): 0%| | 0/10 [00:00<?, ?it/s]
28+
29+
30+
31+
.. parsed-literal::
32+
33+
estimate_templates_with_accumulator (no parallelization): 0%| | 0/10 [00:00<?, ?it/s]
34+
35+
36+
Now we can plot the ``unit_locations`` and ``unit_templates`` using the
37+
appropriate widgets (see the `full list of
38+
widgets <https://spikeinterface.readthedocs.io/en/stable/modules/widgets.html#available-plotting-functions>`__
39+
for more!). These functions output a ``Widget object``. We’ll assign the
40+
unit locations widget to ``fig_units``.
41+
42+
.. code::
43+
44+
fig_units = si.plot_unit_locations(sorting_analyzer)
45+
46+
# Each widget contains a `matplotlib` figure and axis:
47+
print(type(fig_units.figure))
48+
print(type(fig_units.ax))
49+
50+
51+
.. parsed-literal::
52+
53+
<class 'matplotlib.figure.Figure'>
54+
<class 'matplotlib.axes._axes.Axes'>
55+
56+
57+
58+
.. image:: customize_a_plot_files/customize_a_plot_4_1.png
59+
60+
61+
By gaining access to the matplotlib objects, we are able to utilize the
62+
full ``matplotlib`` machinery: adding custom titles, axis labels, ticks,
63+
more plots etc. Let’s customize our unit locations plot. (Note: the
64+
``SpikeInterface`` Team does not endorse the following style
65+
conventions):
66+
67+
.. code::
68+
69+
# Get the widget
70+
fig_units = si.plot_unit_locations(sorting_analyzer)
71+
72+
# Modify the widget's `axis`` to set the title and axes labels
73+
fig_units.ax.set_title("My favorite units", fontname = "Comic Sans MS")
74+
fig_units.ax.set_xlabel("x probe location (um)")
75+
fig_units.ax.set_ylabel("y probe location (um)")
76+
77+
# You can also set custom ticks
78+
fig_units.ax.set_xticks([-60,-30,unit_locations[0,0],30,60])
79+
fig_units.ax.set_xticklabels([-60,-30,"unit_0_x",30,60])
80+
fig_units.ax.set_yticks([-40,-20,0,unit_locations[0,1],40])
81+
fig_units.ax.set_yticklabels([-40,-20,0,"unit_0_y",40])
82+
83+
# Change the limits of the plot
84+
fig_units.ax.set_xlim((-30,50))
85+
fig_units.ax.set_ylim((-50,50))
86+
87+
# And add extra information on the plot
88+
fig_units.ax.text(unit_locations[6,0], unit_locations[6,1]+5, s="UNIT 6!!!", fontname="Courier")
89+
90+
fig_units
91+
92+
93+
94+
95+
.. parsed-literal::
96+
97+
<spikeinterface.widgets.unit_locations.UnitLocationsWidget at 0x147a81520>
98+
99+
100+
101+
102+
.. image:: customize_a_plot_files/customize_a_plot_6_1.png
103+
104+
105+
Beautiful!!!
106+
107+
You can also combine figures into a multi-figure plot. The easiest way
108+
to do this is to set up your figure and axes first, then tell
109+
``SpikeInterface`` which axes it should attach the widget plot to.
110+
Here’s an example of making a unit summary plot.
111+
112+
.. code::
113+
114+
import matplotlib.pyplot as plt
115+
fig, axs = plt.subplots(ncols=2, nrows=1)
116+
117+
unit_id=8
118+
si.plot_unit_locations(sorting_analyzer=sorting_analyzer, ax=axs[0])
119+
si.plot_unit_templates(sorting_analyzer, axes=[axs[1]], unit_ids=[f'{unit_id}'])
120+
121+
axs[0].plot([unit_locations[8,0], unit_locations[8,0]+50], [unit_locations[8,1], unit_locations[8,1]+50])
122+
axs[0].text(unit_locations[8,0]+52, unit_locations[8,1]+52, s=f"Unit {unit_id}")
123+
axs[0].set_title("Unit location", fontsize=10)
124+
125+
fig.suptitle(f"Unit {unit_id} summary", fontfamily="Comic Sans MS", fontsize=20)
126+
127+
fig.tight_layout()
128+
129+
130+
131+
132+
.. image:: customize_a_plot_files/customize_a_plot_8_1.png
133+
134+
135+
For more details on what you can do using matplotlib, check out their
136+
`extensive documentation <https://matplotlib.org/stable/>`__
24.8 KB
Loading
35.2 KB
Loading
53.5 KB
Loading

doc/how_to/index.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,3 +17,4 @@ Guides on how to solve specific, short problems in SpikeInterface. Learn how to.
1717
drift_with_lfp
1818
auto_curation_training
1919
auto_curation_prediction
20+
customize_a_plot

doc/releases/0.102.2.rst

Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
.. _release0.102.2:
2+
3+
SpikeInterface 0.102.2 release notes
4+
------------------------------------
5+
6+
2nd April 2025
7+
8+
Minor release with bug fixes
9+
10+
core:
11+
12+
* Add check that `remove_channel_ids` are in parent recording (#3822)
13+
* Print zarr exception if `super_zarr_open` fails (#3803)
14+
* Add `_precomputable_kwarg_names` to `BaseExtractor` (#3781)
15+
* Fix dict representation in aggregation (numpy 2.0) (#3744)
16+
* Explicit sparsity mask for SparseWaveform (#3742)
17+
* Renaming: `from_time_labels` -> `from_samples_and_labels` (#3724)
18+
* New sparsity (to add Ks clustering in components) (#3717)
19+
20+
extractors:
21+
22+
* Add nwb extractors to API docs (#3810)
23+
* Make sure to use the latest ibllib version - ONE will come along (#3802)
24+
* Better naming for SI units (#3788)
25+
* Add Intan port groups by default (#3753)
26+
* Fix stream names and ids representation in numpy 2.0 (#3751)
27+
* Add warning message for streams with mixed units (#3739)
28+
* Fix: get_streams call in OpenEphysBinaryRecordingExtractor completed (#3738)
29+
* Fix gain inference for "Volts" unit in Plexon2 files (#3728)
30+
* Fix IBL streaming tests (#3718)
31+
* Set max_channel property of MdaSortingExtractor (#3701)
32+
33+
preprocessing:
34+
35+
* Allow preprocessing on dicts of recordings (again) (#3773)
36+
* Update `load_motion_info` to load legacy motion folders (#3772)
37+
* Allow `aggregate_channels` to accept a dict of recordings (#3767)
38+
39+
sorters:
40+
41+
* Add job kwargs to KS4 (#3786)
42+
* Fix KS4 tests (#3768)
43+
* Patch for merging (#3749)
44+
45+
postprocessing:
46+
47+
* Warn instead of print in solve_monopolar (#3736)
48+
49+
curation:
50+
51+
* Support new sortingview and kachery (#3762)
52+
* Improve merging and iterative merging (#3487)
53+
54+
widgets:
55+
56+
* In sorting_summary: `rp_violation` -> `rp_violations` (#3770)
57+
* Support new sortingview and kachery (#3762)
58+
* Pin sortingview version (#3757)
59+
* Fitting scaling factors in waveform/template plots for irregular probe layouts (#3748)
60+
* Fix `extra_properties` propagation in sorting summary and SV string properties (#3716)
61+
* Enhance the CC plots (#3713)
62+
* Add `BaseRasterWidget` (#3661)
63+
* Add LocationsWidget and plot_locations (#3649)
64+
* Adding colorbar support to peak activity widget (#3646)
65+
66+
sortingcomponents:
67+
68+
* Prevent error of trying to delete non-existent variable in sorting components (#3820)
69+
* Ks clustering (#3712)
70+
* Peak SVD motion extraction (#3693)
71+
* Implement motion_aware option in tdc-peeler (#3682)
72+
* Improve peak detection benchmark (#3662)
73+
* improve tdc clustering options (#3658)
74+
* Improve merging and iterative merging (#3487)
75+
76+
motion correction:
77+
78+
* Wrap medicine motion estimation (#3552)
79+
80+
documentation:
81+
82+
* Switch `print` to `warnings.warn` (#3811)
83+
* Add nwb extractors to API docs (#3810)
84+
* Fixed typo in import statement (#3791)
85+
* Clean up all docs warnings (#3746)
86+
* Remove commented-out study classes from comparison (#3743)
87+
88+
continuous integration:
89+
90+
* Update tj-actions changes-files for security (#3787)
91+
* Add torch to test installation (#3706)
92+
93+
packaging:
94+
95+
* Update floor of `setuptools` for metadata (#3800)
96+
* Switch `numba` check to `importlib.util.find_spec` (#3797)
97+
* Cleanup imports and use `importlib.util.find_spec` rather than try-except (#3795)
98+
* Replace deep relative imports with absolute imports (#3766)
99+
* Add psutil to [test] (#3759)
100+
101+
testing:
102+
103+
* Fix KS4 tests (#3768)
104+
105+
Contributors:
106+
107+
* @FrancescoNegri
108+
* @OleBialas
109+
* @abhinavsns
110+
* @alejoe91
111+
* @chrishalcrow
112+
* @guptadivyansh
113+
* @h-mayorquin
114+
* @oliche
115+
* @remi-pr
116+
* @rly
117+
* @samuelgarcia
118+
* @yger
119+
* @zm711
120+
* @zzhmark

examples/how_to/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ with `nbconvert`. Here are the steps (in this example for the `get_started`):
1414

1515
```
1616
>>> jupytext --to notebook get_started.py
17-
>>> jupytext --set-formats ipynb,py get_started.ipynb
17+
>>> jupytext --set-formats ipynb.py get_started.ipynb
1818
```
1919

2020
2. Run the notebook
Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
# ---
2+
# jupyter:
3+
# jupytext:
4+
# cell_metadata_filter: -all
5+
# formats: py:light,ipynb
6+
# text_representation:
7+
# extension: .py
8+
# format_name: light
9+
# format_version: '1.5'
10+
# jupytext_version: 1.17.0
11+
# kernelspec:
12+
# display_name: .venv
13+
# language: python
14+
# name: python3
15+
# ---
16+
17+
# # Customize a plot
18+
19+
# The `SpikeInterface` widgets are designed to have reasonable default plotting options, but
20+
# sometimes you'll want to make adjustments to the plots. The plotting functions all return
21+
# a `Widget` object. These contain and give you access to the underlying matplotlib figure
22+
# and axis, which you can apply any matplotlib machinery to. Let's see how to do this in an
23+
# example, by first making some synthetic data and computing extensions which can be used for plotting.
24+
25+
# +
26+
import spikeinterface.full as si
27+
import matplotlib.pyplot as plt
28+
29+
recording, sorting = si.generate_ground_truth_recording(seed=1205)
30+
sorting_analyzer = si.create_sorting_analyzer(sorting=sorting, recording=recording)
31+
sorting_analyzer.compute({"random_spikes": {'seed': 1205}, "templates": {}, "unit_locations": {}})
32+
33+
unit_locations = sorting_analyzer.get_extension("unit_locations").get_data()
34+
# -
35+
36+
# Now we can plot the `unit_locations` and `unit_templates` using the appropriate widgets
37+
# (see the [full list of widgets](https://spikeinterface.readthedocs.io/en/stable/modules/widgets.html#available-plotting-functions)
38+
# for more!). These functions output a `Widget object`. We'll assign the unit locations widget to `fig_units`.
39+
40+
# +
41+
fig_units = si.plot_unit_locations(sorting_analyzer)
42+
43+
# Each widget contains a `matplotlib` figure and axis:
44+
print(type(fig_units.figure))
45+
print(type(fig_units.ax))
46+
# -
47+
48+
# By gaining access to the matplotlib objects, we are able to utilize the full `matplotlib`
49+
# machinery: adding custom titles, axis labels, ticks, more plots etc. Let's customize
50+
# our unit locations plot. (Note: the `SpikeInterface` Team does not endorse the following style conventions):
51+
52+
# +
53+
# Get the widget
54+
fig_units = si.plot_unit_locations(sorting_analyzer)
55+
56+
# Modify the widget's `axis`` to set the title and axes labels
57+
fig_units.ax.set_title("My favorite units", fontname = "Comic Sans MS")
58+
fig_units.ax.set_xlabel("x probe location (um)")
59+
fig_units.ax.set_ylabel("y probe location (um)")
60+
61+
# You can also set custom ticks
62+
fig_units.ax.set_xticks([-60,-30,unit_locations[0,0],30,60])
63+
fig_units.ax.set_xticklabels([-60,-30,"unit_0_x",30,60])
64+
fig_units.ax.set_yticks([-40,-20,0,unit_locations[0,1],40])
65+
fig_units.ax.set_yticklabels([-40,-20,0,"unit_0_y",40])
66+
67+
# Change the limits of the plot
68+
fig_units.ax.set_xlim((-30,50))
69+
fig_units.ax.set_ylim((-50,50))
70+
71+
# And add extra information on the plot
72+
fig_units.ax.text(unit_locations[6,0], unit_locations[6,1]+5, s="UNIT 6!!!", fontname="Courier")
73+
74+
fig_units
75+
# -
76+
77+
# Beautiful!!!
78+
#
79+
# You can also combine figures into a multi-figure plot. The easiest way to do this is to set up your
80+
# figure and axes first, then tell `SpikeInterface` which axes it should attach the widget plot to.
81+
# Here's an example of making a unit summary plot.
82+
83+
# +
84+
import matplotlib.pyplot as plt
85+
fig, axs = plt.subplots(ncols=2, nrows=1)
86+
87+
unit_id=8
88+
si.plot_unit_locations(sorting_analyzer=sorting_analyzer, ax=axs[0])
89+
si.plot_unit_templates(sorting_analyzer, axes=[axs[1]], unit_ids=[f'{unit_id}'])
90+
91+
axs[0].plot([unit_locations[8,0], unit_locations[8,0]+50], [unit_locations[8,1], unit_locations[8,1]+50])
92+
axs[0].text(unit_locations[8,0]+52, unit_locations[8,1]+52, s=f"Unit {unit_id}")
93+
axs[0].set_title("Unit location", fontsize=10)
94+
95+
fig.suptitle(f"Unit {unit_id} summary", fontfamily="Comic Sans MS", fontsize=20)
96+
97+
fig.tight_layout()
98+
# -
99+
100+
# For more details on what you can do using matplotlib, check out their [extensive documentation](https://matplotlib.org/stable/)

0 commit comments

Comments
 (0)