Skip to content

Fix raster plot handling of segment times where t_start is not zero. - #4790

Open
JoeZiminski wants to merge 24 commits into
mainfrom
fix-raster-plot-segment
Open

JoeZiminski wants to merge 24 commits into
mainfrom
fix-raster-plot-segment

Conversation

@JoeZiminski

@JoeZiminski JoeZiminski commented Sep 16, 2026

Copy link
Copy Markdown
Contributor

This PR updates the raster widgets which was not handling t_start, and also patches the associated get_segment_durations function similarly.

The previous implementation calculated spike times using the sample index and sampling frequency, but not incorporating t_start. Similarly created durations for each segment, and used these in raster plots for things like drawing vertical lines betwen segments.

This PR fixes by using the newer time-getting machinery for spike times, and replacing durations with a dictionary of start-stop times (tuples) per segment called segment_start_stop_times. The reason it's a dictionary not a list is because the segments to display can be sub-selected, and if these are not referred to explicitly it gets complicated as the segments are re-indexed in BaseRasterWidget. durations is just removed, I assume that's okay as was only used internally.

Now get_segment_durations also returns this segment_start_stop_times. Two things are a bit weird with this fuction, one the name is now not great because it returns two things. Secondly it could look to see if theres a recording and if so, get the true segment spike times, but instead always infers them from the spike_vector. This is to keep the previous behaviour, but maybe it can be renamed like get_segment_durations_from_spike_vector.

In the plots below you can see the original issue / fix - in this example the recording has three segments each 10 seconds long starting at [5.0, 25, 50]. The raster plot however all start at t=0 and the segment boundaries are not correct (note motion plot only takes 1 segment).

Before
image

image image

After
image

image image

Code to produce plots below, note that the amplitude plots will not generate as show, as needs #4796

Test code
"""
Generate a multi-segment recording whose segments start at non-zero times,
then plot a raster and motion-correction diagnostics.
"""

import matplotlib.pyplot as plt

import spikeinterface.widgets as sw
from spikeinterface.core import (
    append_recordings,
    append_sortings,
    create_sorting_analyzer,
    generate_ground_truth_recording,
)
from spikeinterface.preprocessing import correct_motion

# When False,  the times are inferred from the spike vector for amplitudes 
# and raster widget (motion info plot requires the recording)
WITH_RECORDING = True


def make_multi_segment_recording(num_segments=3, seed=2205):
    """Build a multi-segment recording and sorting with non-zero segment start times."""

    common_kwargs = dict(
        durations=[10.0],
        sampling_frequency=30000.0,
        num_channels=64,
        num_units=60,
    )

    recordings = []
    sortings = []
    # Offsets so segments do NOT start at time zero.
    start_time_offsets = [5.0, 25, 50]

    for seg in range(num_segments):
        recording, sorting = generate_ground_truth_recording(seed=seed + seg, **common_kwargs)
        # Give this segment a non-zero start time.
        recording.shift_times(shift=start_time_offsets[seg % len(start_time_offsets)])
        recordings.append(recording)
        sortings.append(sorting)

    multi_segment_recording = append_recordings(recordings)
    multi_segment_sorting = append_sortings(sortings)
    return multi_segment_recording, multi_segment_sorting, recordings[0]


def main():
    recording, sorting, motion_recording = make_multi_segment_recording()
    if WITH_RECORDING:
        sorting.register_recording(recording)

    if WITH_RECORDING:
        for seg in range(recording.get_num_segments()):
            print(f"  segment {seg}: start={recording.get_start_time(seg):.1f}s end={recording.get_end_time(seg):.1f}s")

    # Plot a raster of all segments.
    segment_indices = list(range(sorting.get_num_segments()))
    sw.plot_rasters(sorting, segment_indices=segment_indices)

    sorting_analyzer = create_sorting_analyzer(sorting, recording, format="memory")
    sorting_analyzer.compute("random_spikes")
    sorting_analyzer.compute("waveforms")
    sorting_analyzer.compute("templates")
    sorting_analyzer.compute("spike_amplitudes")
    sw.plot_amplitudes(
        sorting_analyzer,
        segment_indices=segment_indices,
        plot_histograms=True,
        plot_legend=False,
    )

    _, motion_info = correct_motion(
        motion_recording,
        preset="kilosort_like",
        output_motion_info=True,
        n_jobs=1,
    )
    sw.plot_motion_info(motion_info, recording=motion_recording, motion_lim=1.0)

    plt.show()


if __name__ == "__main__":
    main()

@JoeZiminski
JoeZiminski marked this pull request as draft September 16, 2026 18:55
@JoeZiminski
JoeZiminski force-pushed the fix-raster-plot-segment branch 2 times, most recently from e322cac to 434d58e Compare September 16, 2026 19:40
@JoeZiminski
JoeZiminski force-pushed the fix-raster-plot-segment branch from 41fa6e9 to 98143d1 Compare September 17, 2026 13:49
@JoeZiminski
JoeZiminski force-pushed the fix-raster-plot-segment branch from 8abc381 to 48ca1c9 Compare September 17, 2026 14:19
@JoeZiminski
JoeZiminski force-pushed the fix-raster-plot-segment branch from aed7a7e to 25de7b4 Compare September 17, 2026 14:46
@JoeZiminski
JoeZiminski force-pushed the fix-raster-plot-segment branch from 6591e5b to 5ae61c4 Compare September 17, 2026 14:57
@JoeZiminski
JoeZiminski force-pushed the fix-raster-plot-segment branch from 5cf7398 to da4456c Compare September 17, 2026 16:28
@JoeZiminski
JoeZiminski force-pushed the fix-raster-plot-segment branch from 7b83d1e to c000d5b Compare September 17, 2026 16:31
color: str = "Gray",
clim: tuple[float, float] | None = None,
alpha: float = 1,
segment_index: int | list[int] | None = None,

@JoeZiminski JoeZiminski Sep 17, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is unused in main, but I guess this is public facing and will need a deprecation warning? (although maybe not if its never used anyway)

@JoeZiminski
JoeZiminski marked this pull request as ready for review September 17, 2026 17:16
@JoeZiminski JoeZiminski changed the title Fix raster plot segment Fix raster plot handling of segment times where t_start is not zero. Sep 17, 2026
@JoeZiminski
JoeZiminski force-pushed the fix-raster-plot-segment branch from 904fecf to 244d985 Compare September 17, 2026 17:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant