Real-time feedback for decoding :: Client Side

This example demonstrates how to setup a real-time feedback mechanism using StimServer and StimClient.

The idea here is to display future stimuli for the class which is predicted less accurately. This allows on-demand adaptation of the stimuli depending on the needs of the classifier.

To run this example, open ipython in two separate terminals. In the first, run and then wait for the message

RtServer: Start

Once that appears, run in the other terminal and the feedback script should start.

All brain responses are simulated from a fiff file to make it easy to test. However, it should be possible to adapt this script for a real experiment.

# Author: Mainak Jas <>
# License: BSD (3-clause)

from mne.realtime import StimClient
from psychopy import visual, core


# Instantiating stimulation client

# Port number must match port number used to instantiate
# StimServer. Any port number above 1000 should be fine
# because they do not require root permission.
stim_client = StimClient('localhost', port=4218)

# create a window
mywin = visual.Window([800, 600], monitor="testMonitor", units="deg")

# create the stimuli

# right checkerboard stimuli
right_cb = visual.RadialStim(mywin, tex='sqrXsqr', color=1, size=5,
                             visibleWedge=[0, 180], radialCycles=4,
                             angularCycles=8, interpolate=False,

# left checkerboard stimuli
left_cb = visual.RadialStim(mywin, tex='sqrXsqr', color=1, size=5,
                            visibleWedge=[180, 360], radialCycles=4,
                            angularCycles=8, interpolate=False,

# fixation dot
fixation = visual.PatchStim(mywin, color=-1, colorSpace='rgb', tex=None,
                            mask='circle', size=0.2)

# the most accurate method is using frame refresh periods
# however, since the actual refresh rate is not known
# we use the Clock
timer1 = core.Clock()
timer2 = core.Clock()

ev_list = list()  # list of events displayed

# start with right checkerboard stimuli. This is required
# because the ev_list.append(ev_list[-1]) will not work
# if ev_list is empty.
trig = 4

# iterating over 50 epochs
for ii in range(50):

    if trig is not None:
        ev_list.append(trig)  # use the last trigger received
        ev_list.append(ev_list[-1])  # use the last stimuli

    # draw left or right checkerboard according to ev_list
    if ev_list[ii] == 3:

    fixation.draw()  # draw fixation
    mywin.flip()  # show the stimuli

    timer1.reset()  # reset timer
    timer1.add(0.75)  # display stimuli for 0.75 sec

    # return within 0.2 seconds (< 0.75 seconds) to ensure good timing
    trig = stim_client.get_trigger(timeout=0.2)

    # wait till 0.75 sec elapses
    while timer1.getTime() < 0:

    fixation.draw()  # draw fixation
    mywin.flip()  # show fixation dot

    timer2.reset()  # reset timer
    timer2.add(0.25)  # display stimuli for 0.25 sec

    # display fixation cross for 0.25 seconds
    while timer2.getTime() < 0:

mywin.close()  # close the window

Gallery generated by Sphinx-Gallery