Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
113 commits
Select commit Hold shift + click to select a range
fae29b2
Begin adding rough implementation.
JoeZiminski Jul 2, 2024
e828429
Doing some basic alignment.
JoeZiminski Jul 9, 2024
020659e
Finish naive alignment to first session.
JoeZiminski Jul 9, 2024
86fcb35
Play around with slope drift for generate_drifting_recording.
JoeZiminski Jul 15, 2024
0f89185
Very minimal first working version.
JoeZiminski Jul 16, 2024
a468205
Start playing around with histogram estimation.
JoeZiminski Jul 30, 2024
639f967
Continue playing with estimation.
JoeZiminski Jul 30, 2024
578d3e2
Continue playing around with estimation.
JoeZiminski Jul 31, 2024
87a05a5
Add rough time estimatino.
JoeZiminski Aug 1, 2024
4dcba7f
To some refactoring.
JoeZiminski Aug 12, 2024
924c6dc
Add in alignment and interpolation functions.
JoeZiminski Aug 13, 2024
7ea7cf2
Fix scaling on histograms and bin_s estimation, add benchmarking init…
JoeZiminski Aug 14, 2024
6324b60
Adding some mp benchmarking.
JoeZiminski Aug 15, 2024
901844e
Small fixes for hpc.
JoeZiminski Aug 15, 2024
a1be9d5
Add arg input for SLURM.
JoeZiminski Aug 15, 2024
027a7c5
sbatch file.
JoeZiminski Aug 15, 2024
1352bbd
small fixes to other methods.
JoeZiminski Aug 15, 2024
0fded75
Start adding widgets.
JoeZiminski Aug 21, 2024
5c48e42
Add first rough nonrigid.
JoeZiminski Aug 23, 2024
1a5c32f
Try a recursive nonrigid alignment, doesn't really work.
JoeZiminski Aug 27, 2024
0d6bbbd
Revert "Try a recursive nonrigid alignment, doesn't really work."
JoeZiminski Aug 27, 2024
dc9e610
Adding a few more options.
JoeZiminski Aug 27, 2024
00b5593
small changes prior to refactoring.
JoeZiminski Aug 28, 2024
83b05e1
Small changes.
JoeZiminski Aug 28, 2024
0a44f3d
Remove old and benchmarking scripts.
JoeZiminski Aug 28, 2024
7764ef2
Begin tidying up.
JoeZiminski Aug 28, 2024
9754ca0
Major refactor, add smoothing, interpolation, better spatial binning.
JoeZiminski Aug 30, 2024
c63f7ee
Update some notes.
JoeZiminski Aug 30, 2024
19b2f84
Tidy up, expose aling to session X.
JoeZiminski Sep 2, 2024
1bf4275
Thinking about trimmed versions and robust xcorr, leave until later.
JoeZiminski Sep 2, 2024
e2eb83c
PLaying with large shifts.
JoeZiminski Sep 3, 2024
74f1ee1
Playing with alignment algorithm, completely fails when rigid shift l…
JoeZiminski Sep 3, 2024
1e2e20f
some small tidying up
JoeZiminski Sep 4, 2024
aeed9f5
Lots of tidying up, need to look into nonrigid more something has reg…
JoeZiminski Sep 5, 2024
9d64118
Look further into rigid, it was working well, but the parameters chos…
JoeZiminski Sep 6, 2024
00255cc
Fix corrected histogram to use same method as compute.
JoeZiminski Sep 6, 2024
1aed8da
Big refactor, getting close to first draft.
JoeZiminski Sep 6, 2024
26dab08
Begin typing and documentation.
JoeZiminski Sep 12, 2024
068130e
Fix from motion correction function, adding typing and docstrings.
JoeZiminski Sep 13, 2024
f0f1089
Docstrings and typing for session_alignment.
JoeZiminski Sep 17, 2024
7d04257
Continue adding docstring / types.
JoeZiminski Sep 27, 2024
1ef398d
Continue with docstrings.
JoeZiminski Sep 30, 2024
e5ea906
Small fixes
JoeZiminski Nov 21, 2024
f8e46c0
Remove a TODO.
JoeZiminski Nov 21, 2024
a8a4899
Add recording shifts argument.
JoeZiminski Nov 21, 2024
88af443
Update time estimate method.
JoeZiminski Nov 22, 2024
1e3edab
Fix time estimate, other tidy ups.
JoeZiminski Nov 27, 2024
af3df0d
gaussian process first draft.
JoeZiminski Nov 29, 2024
5dd94ea
remove some debug stuff from gp first draft.
JoeZiminski Nov 29, 2024
7734252
Very rough introduce 2D versions.
JoeZiminski Nov 29, 2024
2f7b5b8
Add scaling to GP, beter convergence.
JoeZiminski Dec 6, 2024
a12e64d
Tidy up.
JoeZiminski Dec 16, 2024
588ace3
Tidy up and fixes for 'session_alignment.py'
JoeZiminski Dec 16, 2024
e0651cf
Tidying up, begin fixing alignment alg.
JoeZiminski Dec 16, 2024
d6adb24
Remove pickle files.
JoeZiminski Dec 17, 2024
f40d428
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Dec 17, 2024
79cf3e3
Reformatting alignment methods and add 2D, need to tidy up.
JoeZiminski Dec 17, 2024
2785101
delete big files.
JoeZiminski Dec 17, 2024
9a3f5fd
Trying different alg
JoeZiminski Dec 19, 2024
1a91c23
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Dec 19, 2024
7ec6f0b
Playing with alg rigid shift but scales for better rigid shift, okay …
JoeZiminski Dec 19, 2024
dda9745
Testing on the session_alignment side.
JoeZiminski Dec 19, 2024
2e66b90
playing with nonrigid.
JoeZiminski Dec 20, 2024
f3df048
Save.
JoeZiminski Dec 24, 2024
c178702
With additional windowing.
JoeZiminski Dec 24, 2024
941bca9
Doing some tidying, use amplitudes much more TODO!
JoeZiminski Dec 25, 2024
86b1ec3
Remove additional improvements on alignment alg to work on later.
JoeZiminski Jan 13, 2025
19b01ee
First draft add plotting 2D histograms.
JoeZiminski Jan 13, 2025
53292f5
Tidying up, checking alignment function.
JoeZiminski Jan 13, 2025
7677c02
Add 2d histogram plot, move plots to SI widgets.
JoeZiminski Jan 13, 2025
dc56f60
Update playing.py
JoeZiminski Jan 13, 2025
bcaad49
Start adding tests.
JoeZiminski Jan 14, 2025
055c03a
Continue working on tests.
JoeZiminski Jan 15, 2025
35de446
Continue adding tests.
JoeZiminski Jan 16, 2025
60630f3
Continue! working on tests.
JoeZiminski Jan 17, 2025
7a35eec
Tidy up tests and (slightly) improve num_iter handling.
JoeZiminski Jan 20, 2025
ff1baf8
Add how-to doc.
JoeZiminski Jan 21, 2025
2d9817a
Small changes to docs.
JoeZiminski Jan 21, 2025
599365e
Tidying up tests.
JoeZiminski Jan 30, 2025
f99895b
Fixing after rebase.
JoeZiminski Mar 14, 2025
a7a3dcd
Remove files.
JoeZiminski Mar 14, 2025
916991d
Fix tests.
JoeZiminski Mar 14, 2025
417b9ed
Fix bad import.
JoeZiminski Mar 14, 2025
2306a78
Fix tests, tidy up.
JoeZiminski Mar 14, 2025
13f7724
Some more test tidying and documentation.
JoeZiminski Mar 15, 2025
d1f7969
Speed up tests.
JoeZiminski Mar 15, 2025
6887dfb
Continue fixing tests.
JoeZiminski Mar 16, 2025
f8d087a
Finalise tidying up tests.
JoeZiminski Mar 16, 2025
012e760
rework the docs to tutorial, add final TODOs.
JoeZiminski Mar 16, 2025
1c4be1c
Add a few more examples.
JoeZiminski Mar 19, 2025
ff3907e
Add documentation.
JoeZiminski Mar 20, 2025
bec9312
Fix import, remove debugging.
JoeZiminski Mar 20, 2025
d729ef9
Compute log transform after mean / median taken. Tidy up, fix tests.
JoeZiminski Mar 20, 2025
26344ea
Fix tests.
JoeZiminski Feb 6, 2026
ce02146
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Feb 6, 2026
5e8831e
Quick fix.
JoeZiminski Mar 30, 2026
51c9976
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Nov 11, 2026
0d17810
Fix inter-session recording time edges and probe assignment
JoeZiminski Nov 11, 2026
4c836df
Fix pairwise session shift matrix symmetry
JoeZiminski Nov 11, 2026
7ac2311
Rebuild motion interpolators after adding nonrigid session shifts
JoeZiminski Nov 11, 2026
a6f3e76
Return estimated session histogram chunk size
JoeZiminski Nov 11, 2026
fa8d575
Restore entire-session activity histograms
JoeZiminski Nov 11, 2026
b2dc22d
Show all sessions in inter-session alignment widget
JoeZiminski Nov 11, 2026
c666022
Avoid zero tick-label stride for small activity histograms
JoeZiminski Nov 11, 2026
35ed2a0
small fixes
JoeZiminski Nov 11, 2026
240050f
Preserve zero and integer lags when interpolating session alignment
JoeZiminski Nov 11, 2026
a26b50e
Small fixes, and remove chunked mean option as its equivilent to enti…
JoeZiminski Nov 12, 2026
25cb8e5
Merge branch 'main' into inter_session_displacement
JoeZiminski Nov 12, 2026
080deb9
Ruff fixes.
JoeZiminski Nov 12, 2026
94e6454
Fix circular imports, small test fix.
JoeZiminski Nov 12, 2026
77631f5
Fix docs.
JoeZiminski Nov 12, 2026
3520807
Fix docs 2.
JoeZiminski Nov 12, 2026
a44afb6
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Nov 12, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
305 changes: 305 additions & 0 deletions debugging/_test_session_alignment.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,305 @@
from __future__ import annotations

from spikeinterface.generation.session_displacement_generator import generate_session_displacement_recordings
import matplotlib.pyplot as plt
import numpy as np
import pickle
from spikeinterface.preprocessing.inter_session_alignment import (
session_alignment,
plotting_session_alignment,
alignment_utils
)
from spikeinterface.sortingcomponents.peak_detection import detect_peaks
from spikeinterface.sortingcomponents.peak_localization import localize_peaks
import spikeinterface.full as si


# TODO: all of the nonrigid methods (and even rigid) could be having some strange affects on AP
# waveforms. definately needs looking into!

# TODO: ask about best way to chunk, as ofc the peak detection takes
# recording as inputs so cannot use get traces with chunks function as planned.
# TODO: expose trimmed versions, robust xcorr

# Note, the cross correlation is intrinsically limited because for large
# shifts the value is too reduced by the reduction in number of points.
# but, of course cannot scale by number of points due to instability at edges
# This is a major problem, e.g. see the strange results for:
"""
scalings = [np.ones(25), np.r_[np.zeros(10), np.ones(15)]]
recordings_list, _ = generate_session_displacement_recordings(
non_rigid_gradient=None, # 0.05, # 0.05,
num_units=55,
recording_durations=(100, 100, 100, 100),
recording_shifts=(
(0, 0), (0, 250), (0, -150), (0, -210),
),
recording_amplitude_scalings=None, # {"method": "by_amplitude_and_firing_rate", "scalings": scalings},
generate_unit_locations_kwargs={"margin_um": 0, "minimum_z": 0, "maximum_z": 0},
seed=42,
)
"""

"""
TODO: in this case, it is not necessary to run peak detection across
the entire recording, would probably be sufficient to
take a few chunks, of size determined by firing frequency of
the neurons in the recording (or just take user defined size).
For now, run on the entire recording and discuss the best way to
run on chunked sections with Sam.
"""

# with nonrigid shift. This is less of a problem when restricting to a small
# windwo for the nonrigid because even if it fails catistrophically the nonrigid
# error will only be max(non rigid shifts). But its still not good.

# TODO: add different modes (to mean, to nth session...)
# TODO: document that the output is Hz

# TODO: major check, refactor and tidy up
# list out carefully all notes
# handle the case where the passed recordings are not motion correction recordings.

# 3) think about and add new neurons that are introduced when shifted

# 4) add interpolation of the histograms prior to cross correlation
# 5) add robust cross-correlation
# 6) add trimmed methods
# 7) add better way to estimate chunk length.

# try and interpolate /smooth the xcorr. What about smoothing the activity histograms directly?
# look into te akima spline

# TODO: think about the nonrigid alignment, it correlates
# over the entire window. is this wise? try cutting it down a bit?

# TODO: We this interpolate, smooth for xcorr in both rigid and non-rigid case. Think aboout this / check this is ok
# maybe we only want to apply the smoothings etc for nonrigid like KS motion correction

# TODO: try forcing all unit locations to actually
# be within the probe. Add some notes on this because it is confusing.

# 1) write argument checks
# 2) go through with a fine tooth comb, fix all outstanding issues, tidy up,
# plot everything to make sure it is working prior to writing tests.

# 4) to an optimisation shift and scale instead of the current xcorr method.
# 5) finalise estimation of chunk size (skip for now, try a new alignment method)
# and optimal bin size.
# 6) make some presets? should estimate a lot of parameters based on the data, especially for nonrigid.
# these are all basically based on probe geometry.


# Note, shifting can move a unit closer to the channel e.g. if separated
# by 20 um which can increase the signal and make shift estimation harder.

# go through everything and plot to check before writing tests.
# there is a relationship between bin size and nonrigid bins. If bins are
# too small then nonrigid is very unstable. So either choosing a bigger bin
# size or smoothing over the histogram in relation to the number
# of nonrigid bins may make sense.

# the results for nonrigid are very dependent on chosen parameters,
# in particular the number of nonrigid windows, gaussian scale,
# smoothing of the histgram. An optimaisation method may also
# serve to help reduce the number of parameters to choose.

# what you really want is for the window size to adapt to how
# busy the histogram is.

# Suprisingly, the session that is aligned TO can have a
# major affect.

# problem with current:
# - xcorr is not the best for large shifts due to lower num overlapping samples
# -

def _prep_recording(recording, plot=False):
"""
:param recording:
:return:
"""
peaks = detect_peaks(recording, method="locally_exclusive")

peak_locations = localize_peaks(recording, peaks, method="grid_convolution")

if plot:
si.plot_drift_raster_map(
peaks=peaks,
peak_locations=peak_locations,
recording=recording,
clim=(-300, 0), # fix clim for comparability across plots
)
plt.show()

return peaks, peak_locations

MOTION = True # True
SAVE = True
PLOT = False
BIN_UM = 5


if SAVE:
scalings = [np.ones(25), np.r_[np.zeros(10), np.ones(15)]]
recordings_list, _ = generate_session_displacement_recordings(
non_rigid_gradient=None, # 0.05, # 0.05, # 0.05,
num_units=55,
recording_durations=(50, 50), # , 100),
recording_shifts=(
(0, 0),
(0, 75),
),
recording_amplitude_scalings=None, # {"method": "by_amplitude_and_firing_rate", "scalings": scalings},
generate_unit_locations_kwargs={"margin_um": 0, "minimum_z": 0, "maximum_z": 0},
generate_templates_kwargs=dict(
ms_before=1.5,
ms_after=3.0,
mode="sphere", # this is key to maintaining consistent unit positions with shift
unit_params=dict(
alpha=(75, 125.0), # firing rate
spatial_decay=(10, 45),
),
),
seed=42,
)

if not MOTION:
peaks_list = []
peak_locations_list = []

for recording in recordings_list:
peaks, peak_locations = _prep_recording(
recording,
plot=PLOT,
)
peaks_list.append(peaks)
peak_locations_list.append(peak_locations)

# something relatively easy, only 15 units
with open("all_recordings.pickle", "wb") as handle:
pickle.dump((recordings_list, peaks_list, peak_locations_list), handle, protocol=pickle.HIGHEST_PROTOCOL)
else:
# if False:
# TODO: need to align spatial bin calculation between estimate motion and
# estimate session methods so they are more easily interoperable. OR
# just take spatial bin centers from interpoalte!
recordings_list_new = []
peaks_list = []
peak_locations_list = []
motion_info_list = []
from spikeinterface.preprocessing.motion import correct_motion

for i in range(len(recordings_list)):
new_recording, motion_info = correct_motion(
recordings_list[i],
output_motion_info=True,
estimate_motion_kwargs={
"rigid": False,
"win_shape": "gaussian",
"win_step_um": 50,
"win_margin_um": 0,
},
)
recordings_list_new.append(new_recording)
motion_info_list.append(motion_info)
recordings_list = recordings_list_new

with open("all_recordings_motion.pickle", "wb") as handle:
pickle.dump((recordings_list, motion_info_list), handle, protocol=pickle.HIGHEST_PROTOCOL)

if MOTION:
with open("all_recordings_motion.pickle", "rb") as handle:
recordings_list, motion_info_list = pickle.load(handle)
else:
with open("all_recordings.pickle", "rb") as handle:
recordings_list, peaks_list, peak_locations_list = pickle.load(handle)

# TODO: need docs to be super clear from estimate from existing motion,
# as will use motion correction nonrigid bins even if it is suboptimal.

estimate_histogram_kwargs = {
"bin_um": BIN_UM,
"method": "first_eigenvector", # CHANGE NAME!! # TODO: double check scaling
"chunked_bin_size_s": "estimate",
"log_scale": True,
"depth_smooth_um": 10,
"histogram_type": "activity_1d", # "y_only", "locations_2d", "activity_2d"" TOOD: better names!
}
compute_alignment_kwargs = {
"num_shifts_block": None, # TODO: can be in um so comaprable with window kwargs.
"interpolate": False,
"interp_factor": 10,
"kriging_sigma": 1,
"kriging_p": 2,
"kriging_d": 2,
"smoothing_sigma_bin": False, # 0.5,
"smoothing_sigma_window": False, # 0.5,
"akima_interp_nonrigid": False,
}
non_rigid_window_kwargs = {
"rigid": False,
"win_shape": "gaussian",
"win_step_um": 250,
"win_scale_um": 250,
"win_margin_um": None,
"zero_threshold": None,
}

if MOTION:
corrected_recordings_list, extra_info = session_alignment.align_sessions_after_motion_correction(
recordings_list,
motion_info_list,
align_sessions_kwargs={
"alignment_order": "to_middle",
"estimate_histogram_kwargs": estimate_histogram_kwargs,
"compute_alignment_kwargs": compute_alignment_kwargs,
"non_rigid_window_kwargs": non_rigid_window_kwargs,
}
)
peaks_list = [info["peaks"] for info in motion_info_list]
peak_locations_list = [info["peak_locations"] for info in motion_info_list]
else:
corrected_recordings_list, extra_info = session_alignment.align_sessions(
recordings_list,
peaks_list,
peak_locations_list,
alignment_order="to_session_1",
estimate_histogram_kwargs=estimate_histogram_kwargs,
compute_alignment_kwargs=compute_alignment_kwargs,
)


plotting_session_alignment.SessionAlignmentWidget(
recordings_list,
peaks_list,
peak_locations_list,
extra_info["session_histogram_list"],
**extra_info["corrected"],
spatial_bin_centers=extra_info["spatial_bin_centers"],
drift_raster_map_kwargs={"clim":(-250, 0)} # TODO: option to fix this across recordings.
)

plt.show()

# TODO: estimate chunk size Hz needs to be scaled for time? is it not been done correctly?

# No, even two sessions is a mess
# TODO: working assumptions, maybe after rigid, make a template for nonrigid alignment
# as at the moment all nonrigid to eachother is a mess
if False:
A = extra_info["histogram_info_list"][2]["chunked_histograms"]

mean_ = np.mean(A, axis=0)
median_ = alignment_utils.get_chunked_hist_median(A)
supremum_ = alignment_utils.get_chunked_hist_supremum(A)
poisson_ = alignment_utils.get_chunked_hist_poisson_estimate(A)
eigenvector_ = alignment_utils.get_chunked_hist_eigenvector(A)

plt.plot(mean_)
plt.plot(median_)
plt.plot(supremum_)
plt.plot(poisson_)
plt.plot(eigenvector_)
plt.legend(["mean", "median", "supremum", "poisson", "eigenvector"])
plt.show()
1 change: 1 addition & 0 deletions doc/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,7 @@
'subsection_order': ExplicitOrder([
'../examples/tutorials/core',
'../examples/tutorials/extractors',
'../examples/tutorials/preprocessing',
'../examples/tutorials/curation',
'../examples/tutorials/metrics',
'../examples/tutorials/comparison',
Expand Down
14 changes: 14 additions & 0 deletions doc/tutorials_custom_index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,20 @@ These tutorials focus on the :py:mod:`spikeinterface.core` module.
:class-card: gallery-card
:text-align: center

Preprocessing tutorials
-----------------------

.. grid:: 1 2 2 3
:gutter: 2

.. grid-item-card:: Inter-session Alignment
:link-type: ref
:link: sphx_glr_tutorials_preprocessing_plot_7_inter_session_alignment.py
:img-top: /tutorials/preprocessing/images/thumb/sphx_glr_plot_7_inter_session_alignment_thumb.png
:img-alt: Inter-session Alignment
:class-card: gallery-card
:text-align: center

Extractors tutorials
--------------------

Expand Down
2 changes: 2 additions & 0 deletions examples/tutorials/preprocessing/README.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Preprocessing Tutorials
-----------------------
Loading
Loading