Mouse wheel to scroll horizontally in MNE not using matplotlib

  • MNE version: e.g. 0.24.0
  • operating system: Windows 11

“The script creates two plots: one using Matplotlib with mouse wheel scrolling left-right, and the other using self.raw.plot() which doesn’t work (it functions when using arrows). I aim to scroll horizontally using the mouse wheel with MNE-Python, instead of Matplotlib.”

import mne
import matplotlib.pyplot as plt
import numpy as np

class EEGAnalyzer:
def init(self):
self.fig_home = None # Figure for the EEG plot
self.raw = None # Variable to store raw data
self.current_start = 0 # Track the current start position for plotting
self.duration = 10 # Duration (window size) in seconds
self.sampling_rate = None # To store the sampling rate
self.n_channels = None # Number of channels in the data
self.data_range = None # Range for y-axis to simulate channel separation
self.ax = None # Store Axes object for plotting

def on_scroll(self, event):
    """Handle mouse wheel scroll events to move the plot left or right."""
    if self.raw is None or self.ax is None:
        return

    # Adjust the start time based on scroll direction
    if event.button == 'up':
        self.current_start += 1  # Scroll right
    elif event.button == 'down':
        self.current_start = max(0, self.current_start - 1)  # Scroll left, ensure it's non-negative
    else:
        return

    # Update the plot with the new start time
    self.update_plot()

def update_plot(self):
    """Efficiently update the plot based on the current start time."""
    if self.ax is None:
        return

    # Clear the current axes without destroying the figure
    self.ax.cla()

    # Get the current data window (convert time to sample indices)
    start_sample = int(self.current_start * self.sampling_rate)
    stop_sample = int((self.current_start + self.duration) * self.sampling_rate)

    # Extract data and times from the raw object
    data, times = self.raw[:, start_sample:stop_sample]

    # Normalize and offset each channel for visibility
    for i in range(self.n_channels):
        self.ax.plot(times, data[i] + i * self.data_range, color='black')  # Black traces

        # Add the channel names on the right side of each trace
        self.ax.text(times[-1], data[i][-1] + i * self.data_range, self.raw.ch_names[i],
                     verticalalignment='center')

    # Set limits and labels
    self.ax.set_xlim(times[0], times[-1])
    self.ax.set_ylim(np.min(data) - self.data_range, np.max(data) + self.n_channels * self.data_range)
    self.ax.set_xlabel('Time (s)')
    self.ax.set_ylabel('Amplitude (µV)')
    self.ax.set_title('EEG Channels')

    # Redraw the canvas
    self.fig_home.canvas.draw_idle()

def plot_raw_data(self, raw):
    """
    Plots raw EEG data using MNE-Python.

    Args:
        raw: The MNE Raw object containing the EEG data.
    """
    self.raw = raw  # Store the raw data
    self.current_start = 0  # Reset the starting point when loading new data
    self.sampling_rate = raw.info['sfreq']  # Get the sampling frequency
    self.n_channels = len(raw.ch_names)  # Get the number of channels

    # Define the data range for channel separation
    self.data_range = np.max(np.abs(self.raw.get_data()))  # Max amplitude for scaling

    # Create the plot without showing it immediately
    self.fig_home = plt.figure()
    self.ax = self.fig_home.add_subplot(111)  # Create a single subplot
    self.update_plot()  # Initial plot

    # Connect the scroll event to the handler
    self.cid_scroll = self.fig_home.canvas.mpl_connect('scroll_event', self.on_scroll)

    # Use raw.plot() to display EEG data with additional options
    self.raw.plot(
        events=None,
        duration=self.duration,  
        start=self.current_start,
        n_channels=self.n_channels,
        bgcolor='w',
        color=None,
        bad_color=(0.8, 0.8, 0.8),
        event_color='cyan',
        remove_dc=True,
        order=None,
        show_options=True,
        title=None,
        show=False,  # Prevents showing the plot yet
        block=False,
        highpass=None,
        lowpass=None,
        filtorder=4,
        clipping=1.5,
        show_first_samp=False,
        proj=True,
        group_by='type',
        butterfly=False,
        decim='auto',
        noise_cov=None,
        event_id=None,
        show_scrollbars=True,
        show_scalebars=True,
        verbose=None
    )

    plt.show()

analyzer = EEGAnalyzer()
raw = mne.io.read_raw(“C:\000_tmp\fif\3r_eeg.fif”, preload=True)
analyzer.plot_raw_data(raw)