Repository: mne-tools/mne-python

Issue:
find_events fails on TRIUX data with legacy stim channels
Not sure if this is a bug or not, but I think the situation could be improved.

Typically Elekta TRIUX (and recent Vectorview?) systems record triggers only on the digitally coded channel STI101, which contains all trigger information. However, in the data acquisition, there is a possibility of also acquiring 'legacy' trigger channels STI001, STI002, etc. These are binary channels which indicate the corresponding trigger channel being on/off. The main reason for acquiring these would be to support legacy software that does not understand STI101.

The problem is that `mne.find_events` fails (does not find any events) for raw files that contain both STI101 and the legacy channels, because it regards all of them as stim channels and considers them simultaneously. Setting `stim_channel=STI101` remedies the situation. I think an easy solution would be to always use STI101 if it exists, and disregard the legacy channels.

(In some setups, the trigger channel STI201 is also used separately, enabling 32 trigger lines. However this is a rare use case, so I think it doesn't need to be considered by default. Usually STI101 and STI201 are mirrored, i.e. contain identical information.)



Discussion:
Actually this is nicely remedied by returning STI101 in `_get_stim_channel()`
Will submit a PR.

Yeah it should try `STI 014`, `STI101`, then whatever it does now.

I already wrote a small patch but it ended up into the wrong branch and my
attempt at cherry-picking failed. (insert tearful emoji)

On 1 Sep 2016 7:27 p.m., "Eric Larson" notifications@github.com wrote:

> Yeah it should try STI 014, STI101, then whatever it does now.
> 
> —
> You are receiving this because you authored the thread.
> Reply to this email directly, view it on GitHub
> https://github.com/mne-tools/mne-python/issues/3554#issuecomment-244134459,
> or mute the thread
> https://github.com/notifications/unsubscribe-auth/AIGROXJMXpTWFf7w04fItLLxjfzMLyYvks5qlvztgaJpZM4JyiFo
> .

Nothing wrong with a little bit of manual cut and paste in desperate times


Resolving patch:
diff --git a/mne/event.py b/mne/event.py
--- a/mne/event.py
+++ b/mne/event.py
@@ -387,7 +387,7 @@ def find_stim_steps(raw, pad_start=None, pad_stop=None, merge=0,
         affected by the trigger. If None, the config variables
         'MNE_STIM_CHANNEL', 'MNE_STIM_CHANNEL_1', 'MNE_STIM_CHANNEL_2',
         etc. are read. If these are not found, it will default to
-        'STI 014'.
+        'STI101' or 'STI 014', whichever is present.
 
     Returns
     -------
@@ -505,8 +505,8 @@ def find_events(raw, stim_channel=None, output='onset',
         affected by the trigger. If None, the config variables
         'MNE_STIM_CHANNEL', 'MNE_STIM_CHANNEL_1', 'MNE_STIM_CHANNEL_2',
         etc. are read. If these are not found, it will fall back to
-        'STI 014' if present, then fall back to the first channel of type
-        'stim', if present.
+        'STI101' or 'STI 014' if present, then fall back to the first channel
+        of type 'stim', if present.
     output : 'onset' | 'offset' | 'step'
         Whether to report when events start, when events end, or both.
     consecutive : bool | 'increasing'
diff --git a/mne/io/constants.py b/mne/io/constants.py
--- a/mne/io/constants.py
+++ b/mne/io/constants.py
@@ -500,7 +500,7 @@ def __setattr__(self, attr, val):
 # 3560... Miscellaneous
 #
 FIFF.FIFF_MNE_PROJ_ITEM_ACTIVE       = 3560     # Is this projection item active?
-FIFF.FIFF_MNE_EVENT_LIST             = 3561     # An event list (for STI 014)
+FIFF.FIFF_MNE_EVENT_LIST             = 3561     # An event list (for STI101 / STI 014)
 FIFF.FIFF_MNE_HEMI                   = 3562     # Hemisphere association for general purposes
 FIFF.FIFF_MNE_DATA_SKIP_NOP          = 3563     # A data skip turned off in the raw data
 FIFF.FIFF_MNE_ORIG_CH_INFO           = 3564     # Channel information before any changes
diff --git a/mne/utils.py b/mne/utils.py
--- a/mne/utils.py
+++ b/mne/utils.py
@@ -1981,8 +1981,9 @@ def _get_stim_channel(stim_channel, info, raise_error=True):
     """Helper to determine the appropriate stim_channel
 
     First, 'MNE_STIM_CHANNEL', 'MNE_STIM_CHANNEL_1', 'MNE_STIM_CHANNEL_2', etc.
-    are read. If these are not found, it will fall back to 'STI 014' if
-    present, then fall back to the first channel of type 'stim', if present.
+    are read. If these are not found, it will fall back to 'STI101' or
+    'STI 014' if present, then fall back to the first channel of type
+    'stim', if present.
 
     Parameters
     ----------
@@ -2015,7 +2016,10 @@ def _get_stim_channel(stim_channel, info, raise_error=True):
     if ch_count > 0:
         return stim_channel
 
-    if 'STI 014' in info['ch_names']:
+    if 'STI101' in info['ch_names']:  # newer Elekta systems
+        return ['STI101']
+
+    if 'STI 014' in info['ch_names']:  # older Elekta systems
         return ['STI 014']
 
     from .io.pick import pick_types


Test patch: