Running examples

Configure settings

In order to run protocols you need to specify a bpod ‘user_settings.py’ file that should be located at the execution folder.

Example of ‘examples/user_settings.py’ file:

# -*- coding: utf-8-*-

PYBPOD_API_LOG_LEVEL = None

PYBPOD_SESSION_PATH  = 'SESSION-WORKSPACE'

# if you do not define the next variable, the PYBPOD_SESSION
# will assume the current datetime value.
PYBPOD_SESSION = 'SESSION-NAME'

SERIAL_PORT   = '/dev/ttyACM0'

Running protocol examples

Example for running the ‘add_trial_events.py’:

cd PROJECT_FOLDER/examples
python -m function_examples.add_trial_events

Available examples

Obtain Bpod Info

Basic example demonstrating how to initialize Bpod and read version, firmware version and machine type version.

# !/usr/bin/python3
# -*- coding: utf-8 -*-

"""
Get hardware info from Bpod

"""

from pybpodapi.protocol import Bpod
from confapp import conf


my_bpod = Bpod()

my_bpod.close()

print("Target Bpod firmware version: ", conf.TARGET_BPOD_FIRMWARE_VERSION)
print("Firmware version (read from device): ", my_bpod.hardware.firmware_version)
print("Machine type version (read from device): ", my_bpod.hardware.machine_type)

Run the example with:

python -m function_examples.bpod_info

One state example

Simple example of adding a state to the state machine and run it. A timer is used to change state.

# !/usr/bin/python3
# -*- coding: utf-8 -*-

"""
Example adapted from Josh Sanders' original version on Sanworks Bpod repository
"""
from pybpodapi.protocol import Bpod, StateMachine


"""
Run this protocol now
"""

my_bpod = Bpod()

sma = StateMachine(my_bpod)

sma.add_state(
	state_name='myState',
	state_timer=1,
	state_change_conditions={Bpod.Events.Tup: 'exit'},
	output_actions=[])

my_bpod.send_state_machine(sma)

my_bpod.run_state_machine(sma)

print("Current trial info: {0}".format(my_bpod.session.current_trial))

my_bpod.close()

Run the example with:

python -m state_machine_examples.one_state

Light chasing example (3 pokes)

Simulation of a light chasing scenario. Follow the light on 3 pokes.

Connect noseports to ports 1-3.

# !/usr/bin/python3
# -*- coding: utf-8 -*-

"""
Light Chasing example

Follow light on 3 pokes

Connect noseports to ports 1-3.

"""
from pybpodapi.protocol import Bpod, StateMachine


my_bpod = Bpod()

sma = StateMachine(my_bpod)

sma.add_state(
	state_name='Port1Active1',  # Add a state
	state_timer=0,
	state_change_conditions={Bpod.Events.Port1In: 'Port2Active1'},
	output_actions=[(Bpod.OutputChannels.PWM1, 255)])

sma.add_state(
	state_name='Port2Active1',
	state_timer=0,
	state_change_conditions={Bpod.Events.Port2In: 'Port3Active1'},
	output_actions=[(Bpod.OutputChannels.PWM2, 255)])

sma.add_state(
	state_name='Port3Active1',
	state_timer=0,
	state_change_conditions={Bpod.Events.Port3In: 'Port1Active2'},
	output_actions=[(Bpod.OutputChannels.PWM3, 255)])

sma.add_state(
	state_name='Port1Active2',
	state_timer=0,
	state_change_conditions={Bpod.Events.Port1In: 'Port2Active2'},
	output_actions=[(Bpod.OutputChannels.PWM1, 255)])

sma.add_state(
	state_name='Port2Active2',
	state_timer=0,
	state_change_conditions={Bpod.Events.Port2In: 'Port3Active2'},
	output_actions=[(Bpod.OutputChannels.PWM2, 255)])

sma.add_state(
	state_name='Port3Active2',
	state_timer=0,
	state_change_conditions={Bpod.Events.Port3In: 'exit'},
	output_actions=[(Bpod.OutputChannels.PWM3, 255)])

my_bpod.send_state_machine(sma)

my_bpod.run_state_machine(sma)

print("Current trial info: {0}".format(my_bpod.session.current_trial))

my_bpod.close()

Run the example with:

python -m state_machine_examples.light_chasing

Light chasing example (2 pokes)

Simulation of a light chasing scenario. Follow the light on 2 pokes.

Connect noseports to ports 1-2.

# !/usr/bin/python3
# -*- coding: utf-8 -*-

"""
Light Chasing example

Follow light on 2 pokes

Connect noseports to ports 1-2.

"""
from pybpodapi.protocol import Bpod, StateMachine


my_bpod = Bpod()

sma = StateMachine(my_bpod)

sma.add_state(
	state_name='Port1Active1',  # Add a state
	state_timer=0,
	state_change_conditions={Bpod.Events.Port1In: 'Port2Active1'},
	output_actions=[(Bpod.OutputChannels.PWM1, 255)])

sma.add_state(
	state_name='Port2Active1',
	state_timer=0,
	state_change_conditions={Bpod.Events.Port2In: 'Port1Active2'},
	output_actions=[(Bpod.OutputChannels.PWM2, 255)])

sma.add_state(
	state_name='Port1Active2',
	state_timer=0,
	state_change_conditions={Bpod.Events.Port1In: 'Port2Active2'},
	output_actions=[(Bpod.OutputChannels.PWM1, 255)])

sma.add_state(
	state_name='Port2Active2',
	state_timer=0,
	state_change_conditions={Bpod.Events.Port2In: 'exit'},
	output_actions=[(Bpod.OutputChannels.PWM2, 255)])

my_bpod.send_state_machine(sma)

my_bpod.run_state_machine(sma)

print("Current trial info: {0}".format(my_bpod.session.current_trial))

my_bpod.close()

Run the example with:

python -m state_machine_examples.light_chasing_2_pokes

Add trial events

Demonstration of AddTrialEvents used in a simple visual 2AFC session.

AddTrialEvents formats each trial’s data in a human-readable struct, and adds to myBpod.data (to save to disk later)

Connect noseports to ports 1-3.

# !/usr/bin/python3
# -*- coding: utf-8 -*-

"""
Demonstration of AddTrialEvents used in a simple visual 2AFC session.
AddTrialEvents formats each trial's data in a human-readable struct, and adds to myBpod.data (to save to disk later)
Connect noseports to ports 1-3.

Example adapted from Josh Sanders' original version on Sanworks Bpod repository
"""

import random
from pybpodapi.protocol import Bpod, StateMachine

my_bpod = Bpod()

nTrials = 5
trialTypes = [1, 2]  # 1 (rewarded left) or 2 (rewarded right)

for i in range(nTrials):  # Main loop
	print('Trial: ', i + 1)

	thisTrialType = random.choice(trialTypes)  # Randomly choose trial type
	if thisTrialType == 1:
		stimulus = Bpod.OutputChannels.PWM1  # set stimulus channel for trial type 1
		leftAction = 'Reward'
		rightAction = 'Punish'
		rewardValve = 1
	elif thisTrialType == 2:
		stimulus = Bpod.OutputChannels.PWM3  # set stimulus channel for trial type 1
		leftAction = 'Punish'
		rightAction = 'Reward'
		rewardValve = 3

	sma = StateMachine(my_bpod)

	sma.add_state(
		state_name='WaitForPort2Poke',
		state_timer=1,
		state_change_conditions={Bpod.Events.Port2In: 'FlashStimulus'},
		output_actions=[(Bpod.OutputChannels.PWM2, 255)])
	sma.add_state(
		state_name='FlashStimulus',
		state_timer=0.1,
		state_change_conditions={Bpod.Events.Tup: 'WaitForResponse'},
		output_actions=[(stimulus, 255)])
	sma.add_state(
		state_name='WaitForResponse',
		state_timer=1,
		state_change_conditions={Bpod.Events.Port1In: leftAction, Bpod.Events.Port3In: rightAction},
		output_actions=[])
	sma.add_state(
		state_name='Reward',
		state_timer=0.1,
		state_change_conditions={Bpod.Events.Tup: 'exit'},
		output_actions=[(Bpod.OutputChannels.Valve, rewardValve)])  # Reward correct choice
	sma.add_state(
		state_name='Punish',
		state_timer=3,
		state_change_conditions={Bpod.Events.Tup: 'exit'},
		output_actions=[(Bpod.OutputChannels.LED, 1), (Bpod.OutputChannels.LED, 2), (Bpod.OutputChannels.LED, 3)])  # Signal incorrect choice

	my_bpod.send_state_machine(sma)  # Send state machine description to Bpod device

	print("Waiting for poke. Reward: ", 'left' if thisTrialType == 1 else 'right')

	my_bpod.run_state_machine(sma)  # Run state machine

	print("Current trial info: {0}".format(my_bpod.session.current_trial))

my_bpod.close()  # Disconnect Bpod

Run the example with:

python -m function_examples.add_trial_events

Add trial events 2

Similiar to previous example but using a global timer and adding more states.

Connect noseports to ports 1-3.

# !/usr/bin/python3
# -*- coding: utf-8 -*-

"""
Demonstration of AddTrialEvents used in a simple visual 2AFC session.
AddTrialEvents formats each trial's data in a human-readable struct, and adds to myBpod.data (to save to disk later)
Connect noseports to ports 1-3.

Example adapted from Josh Sanders' original version on Sanworks Bpod repository
"""

import random
from pybpodapi.protocol import Bpod, StateMachine


my_bpod = Bpod()

nTrials = 5
graceTime = 5
trialTypes = [1, 2]  # 1 (rewarded left) or 2 (rewarded right)

for i in range(nTrials):  # Main loop
	print('Trial: ', i + 1)

	thisTrialType = random.choice(trialTypes)  # Randomly choose trial type
	if thisTrialType == 1:
		stimulus = Bpod.OutputChannels.PWM1  # set stimulus channel for trial type 1
		leftAction = 'Reward'
		rightAction = 'Punish'
		rewardValve = 1
	elif thisTrialType == 2:
		stimulus = Bpod.OutputChannels.PWM3  # set stimulus channel for trial type 1
		leftAction = 'Punish'
		rightAction = 'Reward'
		rewardValve = 3

	sma = StateMachine(my_bpod)

	sma.set_global_timer_legacy(timer_id=1, timer_duration=graceTime)  # Set timeout

	sma.add_state(
		state_name='WaitForPort2Poke',
		state_timer=1,
		state_change_conditions={Bpod.Events.Port2In: 'FlashStimulus'},
		output_actions=[('PWM2', 255)])

	sma.add_state(
		state_name='FlashStimulus',
		state_timer=0.1,
		state_change_conditions={Bpod.Events.Tup: 'WaitForResponse'},
		output_actions=[(stimulus, 255, Bpod.OutputChannels.GlobalTimerTrig, 1)])

	sma.add_state(
		state_name='WaitForResponse',
		state_timer=1,
		state_change_conditions={Bpod.Events.Port1In: leftAction,
		                         Bpod.Events.Port3In: rightAction,
		                         Bpod.Events.Port2In: 'Warning',
		                         Bpod.Events.GlobalTimer1_End: 'MiniPunish'},
		output_actions=[])

	sma.add_state(
		state_name='Warning',
		state_timer=0.1,
		state_change_conditions={Bpod.Events.Tup: 'WaitForResponse',
		                         Bpod.Events.GlobalTimer1_End: 'MiniPunish'},
		output_actions=[(Bpod.OutputChannels.LED, 1),
		                (Bpod.OutputChannels.LED, 2),
		                (Bpod.OutputChannels.LED, 3)])  # Reward correct choice

	sma.add_state(
		state_name='Reward',
		state_timer=0.1,
		state_change_conditions={Bpod.Events.Tup: 'exit'},
		output_actions=[(Bpod.OutputChannels.Valve, rewardValve)])  # Reward correct choice

	sma.add_state(
		state_name='Punish',
		state_timer=3,
		state_change_conditions={Bpod.Events.Tup: 'exit'},
		output_actions=[(Bpod.OutputChannels.LED, 1),
		                (Bpod.OutputChannels.LED, 2),
		                (Bpod.OutputChannels.LED, 3)])  # Signal incorrect choice

	sma.add_state(
		state_name='MiniPunish',
		state_timer=1,
		state_change_conditions={Bpod.Events.Tup: 'exit'},
		output_actions=[(Bpod.OutputChannels.LED, 1),
		                (Bpod.OutputChannels.LED, 2),
		                (Bpod.OutputChannels.LED, 3)])  # Signal incorrect choice

	my_bpod.send_state_machine(sma)  # Send state machine description to Bpod device

	print("Waiting for poke. Reward: ", 'left' if thisTrialType == 1 else 'right')

	my_bpod.run_state_machine(sma)  # Run state machine

	print("Current trial info: {0}".format(my_bpod.session.current_trial))

my_bpod.close()  # Disconnect Bpod

Run the example with:

python -m function_examples.add_trial_events2

Manual override

Manually interact with Bpod hardware. For a detailed explanation, please refer to Manual control of Bpod.

# !/usr/bin/python3
# -*- coding: utf-8 -*-

"""
Manually set values on Bpod channels via serial instructions.

Example adapted from Josh Sanders' original version on Sanworks Bpod repository
"""

import time

from pybpodapi.protocol import Bpod

import examples.settings as settings



my_bpod = Bpod()

wait_active_time_ms = 2

### INPUTS - BNC (1, 2) ###
print("Set BNC1 (Input) to a value")
my_bpod.manual_override(Bpod.ChannelTypes.INPUT, Bpod.ChannelNames.BNC, channel_number=1, value=12)
time.sleep(wait_active_time_ms)

print("Set BNC2 (Input) to a value")
my_bpod.manual_override(Bpod.ChannelTypes.INPUT, Bpod.ChannelNames.BNC, channel_number=2, value=15)
time.sleep(wait_active_time_ms)

### INPUTS - PWM (1..4) ###
print("Set PWM1 (Input) to a value")
my_bpod.manual_override(Bpod.ChannelTypes.INPUT, 'Port', channel_number=1, value=12)
time.sleep(wait_active_time_ms)

print("Set PWM2 (Input) to a value")
my_bpod.manual_override(Bpod.ChannelTypes.INPUT, 'Port', channel_number=2, value=13)
time.sleep(wait_active_time_ms)

print("Set PWM3 (Input) to a value")
my_bpod.manual_override(Bpod.ChannelTypes.INPUT, 'Port', channel_number=3, value=14)
time.sleep(wait_active_time_ms)

print("Set PWM3 (Input) to a value")
my_bpod.manual_override(Bpod.ChannelTypes.INPUT, 'Port', channel_number=4, value=15)
time.sleep(wait_active_time_ms)


### PORT 1 LED ###

print("Set LED of port 1 to max intensity")
my_bpod.manual_override(Bpod.ChannelTypes.OUTPUT, Bpod.ChannelNames.PWM, channel_number=1, value=255)
time.sleep(wait_active_time_ms)

print("Set LED of port 1 to lower intensity")
my_bpod.manual_override(Bpod.ChannelTypes.OUTPUT, Bpod.ChannelNames.PWM, channel_number=1, value=8)
time.sleep(wait_active_time_ms)

print("Set LED of port 1 to zero intensity")
my_bpod.manual_override(Bpod.ChannelTypes.OUTPUT, Bpod.ChannelNames.PWM, channel_number=1, value=0)
time.sleep(1)

### PORT 2 LED ###

print("Set LED of port 2 to max intensity")
my_bpod.manual_override(Bpod.ChannelTypes.OUTPUT, Bpod.ChannelNames.PWM, channel_number=2, value=255)
time.sleep(wait_active_time_ms)

print("Set LED of port 2 to lower intensity")
my_bpod.manual_override(Bpod.ChannelTypes.OUTPUT, Bpod.ChannelNames.PWM, channel_number=2, value=8)
time.sleep(wait_active_time_ms)

print("Set LED of port 2 to zero intensity")
my_bpod.manual_override(Bpod.ChannelTypes.OUTPUT, Bpod.ChannelNames.PWM, channel_number=2, value=0)
time.sleep(1)  # Wait 1s

### PORT 1 VALVE ###

print("Set valve of port 1 to open")
my_bpod.manual_override(Bpod.ChannelTypes.OUTPUT, Bpod.ChannelNames.VALVE, 1, value=1)
time.sleep(wait_active_time_ms)

print("Set valve of port 1 to close")
my_bpod.manual_override(Bpod.ChannelTypes.OUTPUT, Bpod.ChannelNames.VALVE, 1, value=0)
time.sleep(1)  # Wait 1s

### PORT 3 VALVE ###

print("Set valve of port 3 to open")
my_bpod.manual_override(Bpod.ChannelTypes.OUTPUT, Bpod.ChannelNames.VALVE, channel_number=3, value=1)
time.sleep(wait_active_time_ms)  # Wait 250ms

print("Set valve of port 3 to close")
my_bpod.manual_override(Bpod.ChannelTypes.OUTPUT, Bpod.ChannelNames.VALVE, channel_number=3, value=0)
time.sleep(1)  # Wait 1s

### PORT 2 BNC ###

print("Set BNC output ch2 to high")
my_bpod.manual_override(Bpod.ChannelTypes.OUTPUT, Bpod.ChannelNames.BNC, channel_number=2, value=1)
time.sleep(0.01)  # Wait 10ms

print("Set BNC output ch2 to low")
my_bpod.manual_override(Bpod.ChannelTypes.OUTPUT, Bpod.ChannelNames.BNC, channel_number=2, value=0)
time.sleep(1)  # Wait 1s

### PORT 3 Wire ###

print("Set Wire output ch3 to high")
my_bpod.manual_override(Bpod.ChannelTypes.OUTPUT, Bpod.ChannelNames.WIRE, channel_number=3, value=1)
time.sleep(0.01)  # Wait 10ms

print("Set Wire output ch3 to low")
my_bpod.manual_override(Bpod.ChannelTypes.OUTPUT, Bpod.ChannelNames.WIRE, channel_number=3, value=0)
time.sleep(1)  # Wait 1s

### PORT 2 Serial ###

print("Send byte 65 on UART port 2")
my_bpod.manual_override(Bpod.ChannelTypes.OUTPUT, Bpod.ChannelNames.SERIAL, channel_number=2, value=65)
time.sleep(0.01)  # Wait 10ms

print("Send byte 66 on UART port 1")
my_bpod.manual_override(Bpod.ChannelTypes.OUTPUT, Bpod.ChannelNames.SERIAL, channel_number=1, value=66)

# Stop Bpod
my_bpod.close()  # Sends a termination byte and closes the serial port. PulsePal stores current params to its EEPROM.

Run the example with:

python -m function_examples.manual_override

Serial messages

Example on how to use serial capabilities of Bpod.

# !/usr/bin/python3
# -*- coding: utf-8 -*-

"""
Example adapted from Josh Sanders' original version on Sanworks Bpod repository
"""

import time

from pybpodapi.protocol import Bpod


my_bpod = Bpod()

print("Send byte 65 on UART port 1 - by default, this is ASCII 'A'")
my_bpod.manual_override(Bpod.ChannelTypes.OUTPUT, Bpod.ChannelNames.SERIAL, 1, 65)
time.sleep(1)  # Wait 1s

print("Set byte 65 ('A') on UART port 1 to trigger a 3-byte message: 'BCD'")
my_bpod.load_serial_message(1, 65, [66, 67, 68])
# Now, the same command has a different result
my_bpod.manual_override(Bpod.ChannelTypes.OUTPUT, Bpod.ChannelNames.SERIAL, channel_number=1, value=65)
time.sleep(1)  # Wait 1s

print("Reset the serial message library. Bytes will now pass through again.")
my_bpod.reset_serial_messages()
# Back to 'A'
my_bpod.manual_override(Bpod.ChannelTypes.OUTPUT, Bpod.ChannelNames.SERIAL, channel_number=1, value=65)

# Stop Bpod
my_bpod.close()  # Sends a termination byte and closes the serial port. PulsePal stores current params to its EEPROM.

Run the example with:

python -m function_examples.serial_messages

Global timers examples

Several examples demonstrating how to interact with Bpod timers.

# !/usr/bin/python3
# -*- coding: utf-8 -*-

"""
Example adapted from Josh Sanders' original version on Sanworks Bpod repository
"""
from pybpodapi.protocol import Bpod, StateMachine



my_bpod = Bpod()

sma = StateMachine(my_bpod)

# Set global timer 1 for 3 seconds
sma.set_global_timer_legacy(timer_id=1, timer_duration=3)

sma.add_state(
	state_name='TimerTrig',  # Trigger global timer
	state_timer=0,
	state_change_conditions={Bpod.Events.Tup: 'Port1Lit'},
	output_actions=[(Bpod.OutputChannels.GlobalTimerTrig, 1)])

sma.add_state(
	state_name='Port1Lit',  # Infinite loop (with next state). Only a global timer can save us.
	state_timer=.25,
	state_change_conditions={Bpod.Events.Tup: 'Port3Lit', Bpod.Events.GlobalTimer1_End: 'exit'},
	output_actions=[(Bpod.OutputChannels.PWM1, 255)])

sma.add_state(
	state_name='Port3Lit',
	state_timer=.25,
	state_change_conditions={Bpod.Events.Tup: 'Port1Lit', Bpod.Events.GlobalTimer1_End: 'exit'},
	output_actions=[(Bpod.OutputChannels.PWM3, 255)])

my_bpod.send_state_machine(sma)

my_bpod.run_state_machine(sma)

print("Current trial info: {0}".format(my_bpod.session.current_trial) )

my_bpod.close()

Run the example with:

python -m state_machine_examples.global_timer_example
# !/usr/bin/python3
# -*- coding: utf-8 -*-

"""
Example adapted from Josh Sanders' original version on Sanworks Bpod repository
"""
from pybpodapi.protocol import Bpod, StateMachine

"""
Run this protocol now
"""

my_bpod = Bpod()

sma = StateMachine(my_bpod)

# Set global timer 1 for 3 seconds, following a 1.5 second onset delay after trigger. Link to channel BNC2.
sma.set_global_timer(timer_id=1, timer_duration=3, on_set_delay=1.5, channel='BNC2')

sma.add_state(
	state_name='TimerTrig',  # Trigger global timer
	state_timer=0,
	state_change_conditions={Bpod.Events.Tup: 'Port1Lit'},
	output_actions=[(Bpod.OutputChannels.GlobalTimerTrig, 1)])

sma.add_state(
	state_name='Port1Lit',  # Infinite loop (with next state). Only a global timer can save us.
	state_timer=.25,
	state_change_conditions={Bpod.Events.Tup: 'Port3Lit', 'GlobalTimer1_End': 'exit'},
	output_actions=[(Bpod.OutputChannels.PWM1, 255)])

sma.add_state(
	state_name='Port3Lit',
	state_timer=.25,
	state_change_conditions={Bpod.Events.Tup: 'Port1Lit', 'GlobalTimer1_End': 'exit'},
	output_actions=[(Bpod.OutputChannels.PWM3, 255)])

my_bpod.send_state_machine(sma)

my_bpod.run_state_machine(sma)

print("Current trial info: {0}".format(my_bpod.session.current_trial))

my_bpod.close()

Run the example with:

python -m state_machine_examples.global_timer_example_digital
# !/usr/bin/python3
# -*- coding: utf-8 -*-

"""
Example state machine: A global timer triggers passage through two infinite loops. It is
triggered in the first state, but begins measuring its 3-second Duration
after a 1.5s onset delay. During the onset delay, an infinite loop
toggles two port LEDs (Port1, Port3) at low intensity. When the timer begins measuring,
it sets port 2 LED to maximum brightness, and triggers transition to a second infinite loop with brighter port 1+3 LEDs.
When the timer's 3 second duration elapses, Port2LED is returned low,
and a GlobalTimer1_End event occurs (handled by exiting the state machine).


Example adapted from Josh Sanders' original version on Sanworks Bpod repository
"""
from pybpodapi.protocol import Bpod, StateMachine

"""
Run this protocol now
"""

my_bpod = Bpod()

sma = StateMachine(my_bpod)

# Set global timer 1 for 3 seconds, following a 1.5 second onset delay after trigger. Link to LED of port 2.
sma.set_global_timer(timer_id=1, timer_duration=3, on_set_delay=1.5, channel=Bpod.OutputChannels.PWM2, on_message=255)

sma.add_state(
	state_name='TimerTrig',  # Trigger global timer
	state_timer=0,
	state_change_conditions={Bpod.Events.Tup: 'Port1Lit_Pre'},
	output_actions=[('GlobalTimerTrig', 1)])

sma.add_state(
	state_name='Port1Lit_Pre',
	state_timer=.25,
	state_change_conditions={Bpod.Events.Tup: 'Port3Lit_Pre', Bpod.Events.GlobalTimer1_Start: 'Port1Lit_Post'},
	output_actions=[(Bpod.OutputChannels.PWM1, 16)])

sma.add_state(
	state_name='Port3Lit_Pre',
	state_timer=.25,
	state_change_conditions={Bpod.Events.Tup: 'Port1Lit_Pre', Bpod.Events.GlobalTimer1_Start: 'Port3Lit_Post'},
	output_actions=[(Bpod.OutputChannels.PWM3, 16)])

sma.add_state(
	state_name='Port1Lit_Post',
	state_timer=.25,
	state_change_conditions={Bpod.Events.Tup: 'Port3Lit_Post', Bpod.Events.GlobalTimer1_End: 'exit'},
	output_actions=[(Bpod.OutputChannels.PWM1, 255)])

sma.add_state(
	state_name='Port3Lit_Post',
	state_timer=.25,
	state_change_conditions={Bpod.Events.Tup: 'Port1Lit_Post', Bpod.Events.GlobalTimer1_End: 'exit'},
	output_actions=[(Bpod.OutputChannels.PWM3, 255)])

my_bpod.send_state_machine(sma)

my_bpod.run_state_machine(sma)

print("Current trial info: {0}".format(my_bpod.session.current_trial))

my_bpod.close()

Run the example with:

python -m state_machine_examples.global_timer_start_and_end_events

Global counter example

After poke2 (PWM2) LED turns off, one will have an infinite loop between LED of poke1 (PWM1) and LED of poke3 (PWM1).

To interrupt the infinite loop one have to interrupt poke1 or poke3 a number of times equal to threshold (in this case is 5 times).

# !/usr/bin/python3
# -*- coding: utf-8 -*-

"""
Example adapted from Josh Sanders' original version on Sanworks Bpod repository

After poke2 (PWM2) LED turns off, one will have an infinite loop between LED of poke1 (PWM1) and LED of poke3 (PWM1).

To interrupt the infinite loop one have to interrupt poke1 or poke3 a number of times equal to threshold (in this case is 5 times).

"""
from pybpodapi.protocol import Bpod, StateMachine

my_bpod = Bpod()

sma = StateMachine(my_bpod)

sma.set_global_counter(counter_number=1, target_event='Port1In', threshold=5)

sma.add_state(
	state_name='InitialDelay',
	state_timer=2,
	state_change_conditions={Bpod.Events.Tup: 'ResetGlobalCounter1'},
	output_actions=[(Bpod.OutputChannels.PWM2, 255)])

sma.add_state(
	state_name='ResetGlobalCounter1',
	state_timer=0,
	state_change_conditions={Bpod.Events.Tup: 'Port1Lit'},
	output_actions=[(Bpod.OutputChannels.GlobalCounterReset, 1)])

sma.add_state(
	state_name='Port1Lit',  # Infinite loop (with next state). Only a global counter can save us.
	state_timer=.25,
	state_change_conditions={Bpod.Events.Tup: 'Port3Lit', 'GlobalCounter1_End': 'exit'},
	output_actions=[(Bpod.OutputChannels.PWM1, 255)])

sma.add_state(
	state_name='Port3Lit',
	state_timer=.25,
	state_change_conditions={Bpod.Events.Tup: 'Port1Lit', 'GlobalCounter1_End': 'exit'},
	output_actions=[(Bpod.OutputChannels.PWM3, 255)])

my_bpod.send_state_machine(sma)

my_bpod.run_state_machine(sma)

print("Current trial info: {0}".format(my_bpod.session.current_trial))

my_bpod.close()

Run the example with:

python -m state_machine_examples.global_counter_example

Setting a condition example

Example on how to set a condition.

# !/usr/bin/python3
# -*- coding: utf-8 -*-

"""
Example adapted from Josh Sanders' original version on Sanworks Bpod repository
"""
from pybpodapi.protocol import Bpod, StateMachine


"""
Run this protocol now
"""

my_bpod = Bpod()

sma = StateMachine(my_bpod)

sma.set_condition(condition_number=1, condition_channel='Port2', channel_value=1)

sma.add_state(
	state_name='Port1Light',
	state_timer=1,
	state_change_conditions={Bpod.Events.Tup: 'Port2Light'},
	output_actions=[(Bpod.OutputChannels.PWM1, 255)])

sma.add_state(
	state_name='Port2Light',
	state_timer=1,
	state_change_conditions={Bpod.Events.Tup: 'Port3Light', Bpod.Events.Condition1: 'Port3Light'},
	output_actions=[(Bpod.OutputChannels.PWM2, 255)])

sma.add_state(
	state_name='Port3Light',
	state_timer=1,
	state_change_conditions={Bpod.Events.Tup: 'exit'},
	output_actions=[(Bpod.OutputChannels.PWM3, 255)])

my_bpod.send_state_machine(sma)

my_bpod.run_state_machine(sma)

print("Current trial info: {0}".format(my_bpod.session.current_trial))

my_bpod.close()

Run the example with:

python -m state_machine_examples.condition_example

UART triggered state example

Example on how a UART event can trigger a state change.

# !/usr/bin/python3
# -*- coding: utf-8 -*-

"""
Example adapted from Josh Sanders' original version on Sanworks Bpod repository
"""
from pybpodapi.protocol import Bpod, StateMachine
"""
Run this protocol now
"""

my_bpod = Bpod()

sma = StateMachine(my_bpod)

sma.add_state(
	state_name='Port1Light',
	state_timer=0,
	state_change_conditions={Bpod.Events.Serial2_3: 'Port2Light'},  # Go to Port2Light when byte 0x3 arrives on UART port 2
	output_actions=[(Bpod.OutputChannels.PWM1, 255)])

sma.add_state(
	state_name='Port2Light',
	state_timer=0,
	state_change_conditions={Bpod.Events.Tup: 'exit'},
	output_actions=[(Bpod.OutputChannels.PWM2, 255)])

my_bpod.send_state_machine(sma)

my_bpod.run_state_machine(sma)

print("Current trial info: ", my_bpod.session.current_trial)

my_bpod.close()

Run the example with:

python -m state_machine_examples.uart_triggered_state_change