⏱ Trigger System for EEG/MEG: Trigger Dictionary + TriggerSender
¶
Store your event codes in a plain dictionary and let TriggerSender
handle the dispatch. This keeps your configuration centralized and your send logic simple.
🧵 Summary of Key Methods¶
TriggerSender
¶
Purpose |
Method |
---|---|
Send a trigger |
|
Use mock/debug mode |
|
Add hooks (start/end) |
|
Control post-delay |
|
🗂 1. Prepare a Trigger Dictionary¶
Store event labels (e.g., “cue_onset”, “response”) as keys in a dictionary with integer codes as values.
A. Define manually¶
triggers = {
"cue_onset": 32,
"key_press": 33,
}
B. Load from YAML¶
YAML format:
triggers:
cue_onset: 32
key_press: 33
Code:
import yaml
with open("trigger_config.yaml") as f:
triggers = yaml.safe_load(f)["triggers"]
C. Get a code¶
code = triggers["key_press"] # returns 33
2. Sending Triggers with TriggerSender
¶
TriggerSender handles the dispatch logic. It wraps your actual send function (e.g., serial port) and can also run in mock/debug mode.
A. Real device example¶
def send_to_port(code):
serial_port.write(bytes([code]))
sender = TriggerSender(send_to_port)
B. Mock mode for testing¶
sender = TriggerSender(mock=True)
C. Sending a trigger¶
sender.send(triggers["cue_onset"])
This prints:
[MockTrigger] Sent code: 32
[Trigger] Trigger sent: 32
3. Optional Hooks and Delays¶
You can register actions before/after sending triggers (e.g., opening and closing ports):
sender = TriggerSender(
trigger_func=send_to_port,
on_trigger_start=lambda: print("Opening port..."),
on_trigger_end=lambda: print("Closing port..."),
post_delay=0.005 # Wait 5ms after sending
)
4. Realistic Example¶
Here we used mock mode for testing and a serial port for real device communication.
trigger_config = {
**config.get('triggers', {})
}
ser = serial.serial_for_url("loop://", baudrate=115200, timeout=1)
triggersender = TriggerSender(
trigger_func=lambda code: ser.write([1, 225, 1, 0, (code)]),
post_delay=0.005,
on_trigger_start=lambda: ser.open() if not ser.is_open else None,
on_trigger_end=lambda: ser.close()
)
Using a trigger dictionary with TriggerSender
keeps configuration and logic separated, making your experiment easier to debug, replicate, and maintain.