Repository: mne-tools/mne-python

Issue:
ENH: mne.gui.coregistration automatically changes subject to fsaverage
mne version: MNE 0.14.dev0
OS: Ubuntu 16.04.1 LTS

whenever I open a new Head Shape Source File, the current subject is automatically changed to fsaverage.

the only way for me to work now is to delete the symbolic link that freesurfer creates in the subjects folder and recreate it after finishing all the coregistrations.





Discussion:
This is not a bug, but maybe there is a way to improve it. The GUI should look for an MRI subject name that equals the beginning go the Head Shape source filename. If none is found we assume you want to use fsaverage instead. What subject would you want it to change to instead? Are you using a different standard brain?

Thank you for the prompt response.

No I'm using fsaverage. I was going to ask first if it was a feature but I thought it was too weird to be a feature.

Indeed the files where generated by different groups and they have different naming conventions.

I could rename them, but I don't really understand the feature: If the subject is on the top left of the screen, the idea is not to first select the subject you want to work with, and later select the other files? Perhaps just create a filter when selecting the Head Shape file, but allow the user to overwrite it? 

Even better, include a parameter when calling mne coreg to disable this automatic feature? 

If this would be possible I could change the name of the issue from BUG to ENH, otherwise I'll just close it.

I could add a checkbox to make it optional.

> I don't really understand the feature: If the subject is on the top left of the screen, the idea is not to first select the subject you want to work with, and later select the other files?

You’re right about this. Would it be more logical to put the Head Shape Source section above the MRI?  

> I could add a checkbox to make it optional.

I would favor a parameter in the command line, since I rather write a
script than click in the checkbox every time ;)

but the checkbox would already avoid deleting the the fsaverage folder and
renaming all the files one by one ( they don't really have a proper naming
convention now :/ )

> You’re right about this. Would it be more logical to put the Head Shape
> Source section above the MRI?

Not Sure about that... I seems logical to first pick MRI, then MRI
fiducials, then digitization info, then rotate/translate digitization into
MRI space.

I think the option to disable the automatic behavior, which I can see that
saves time to people that do not want to click in the first listbox with
users AND click again to select the digitization file, should be enough.

Of course, it can be exposed as argument, but you probably also want the checkbox for the times you forget to specify the argument :)

> Of course, it can be exposed as argument, but you probably also want the
> checkbox for the times you forget to specify the argument :)
> 
> True. :)

Another nice option would be to automatically pick the digitization file
matching the subject selected on the list (the other way around). And if
none is found, clear the digitization field.

Indeed it is weird that, when processing a batch of subjects, the old
digitization file is still selected after changing the subject on the top.
Now I see that this is probably because people only change the digitization
file instead, and the subject changes automatically.

For this you would need to specify the digitization folder in advance
though, similar to specifying the subjects folder for freesurfer (used to
populate the list one the top, I'm guessing...).

> On Nov 11, 2016, at 12:16 PM, Leonardo S. Barbosa notifications@github.com wrote:
> 
> > Of course, it can be exposed as argument, but you probably also want the
> > checkbox for the times you forget to specify the argument :)
> > 
> > True. :)
> 
> Another nice option would be to automatically pick the digitization file
> matching the subject selected on the list (the other way around). And if
> none is found, clear the digitization field.
> 
> Indeed it is weird that, when processing a batch of subjects, the old
> digitization file is still selected after changing the subject on the top.
> Now I see that this is probably because people only change the digitization
> file instead, and the subject changes automatically.
> 
> For this you would need to specify the digitization folder in advance
> though, similar to specifying the subjects folder for freesurfer (used to
> populate the list one the top, I'm guessing…).

This would be harder, I think conventions for digitization files might vary more…. we use `MEG/subject_name/something-raw.fiff`, so it’s more nested than the MRIs...

How would clearing the field help, wouldn’t you still have to click the same number of times to load the next one?


Resolving patch:
diff --git a/mne/commands/mne_coreg.py b/mne/commands/mne_coreg.py
--- a/mne/commands/mne_coreg.py
+++ b/mne/commands/mne_coreg.py
@@ -28,13 +28,19 @@ def run():
                       default=False, help="Option for small screens: Combine "
                       "the data source panel and the coregistration panel "
                       "into a single panel with tabs.")
+    parser.add_option("--no-guess-mri", dest="guess_mri_subject",
+                      action='store_false', default=True,
+                      help="Prevent the GUI from automatically guessing and "
+                      "changing the MRI subject when a new head shape source "
+                      "file is selected.")
 
     options, args = parser.parse_args()
 
     with ETSContext():
         mne.gui.coregistration(options.tabbed, inst=options.inst,
                                subject=options.subject,
-                               subjects_dir=options.subjects_dir)
+                               subjects_dir=options.subjects_dir,
+                               guess_mri_subject=options.guess_mri_subject)
     if is_main:
         sys.exit(0)
 
diff --git a/mne/gui/__init__.py b/mne/gui/__init__.py
--- a/mne/gui/__init__.py
+++ b/mne/gui/__init__.py
@@ -24,7 +24,7 @@ def combine_kit_markers():
 
 
 def coregistration(tabbed=False, split=True, scene_width=500, inst=None,
-                   subject=None, subjects_dir=None):
+                   subject=None, subjects_dir=None, guess_mri_subject=None):
     """Coregister an MRI with a subject's head shape.
 
     The recommended way to use the GUI is through bash with::
@@ -50,6 +50,9 @@ def coregistration(tabbed=False, split=True, scene_width=500, inst=None,
     subjects_dir : None | path
         Override the SUBJECTS_DIR environment variable
         (sys.environ['SUBJECTS_DIR'])
+    guess_mri_subject : bool
+        When selecting a new head shape file, guess the subject's name based
+        on the filename and change the MRI subject accordingly (default True).
 
     Notes
     -----
@@ -64,7 +67,7 @@ def coregistration(tabbed=False, split=True, scene_width=500, inst=None,
     _check_backend()
     from ._coreg_gui import CoregFrame, _make_view
     view = _make_view(tabbed, split, scene_width)
-    gui = CoregFrame(inst, subject, subjects_dir)
+    gui = CoregFrame(inst, subject, subjects_dir, guess_mri_subject)
     gui.configure_traits(view=view)
     return gui
 
diff --git a/mne/gui/_coreg_gui.py b/mne/gui/_coreg_gui.py
--- a/mne/gui/_coreg_gui.py
+++ b/mne/gui/_coreg_gui.py
@@ -69,6 +69,7 @@ class CoregModel(HasPrivateTraits):
     hsp = Instance(InstSource, ())
 
     # parameters
+    guess_mri_subject = Bool(True)  # change MRI subject when dig file changes
     grow_hair = Float(label="Grow Hair [mm]", desc="Move the back of the MRI "
                       "head outwards to compensate for hair on the digitizer "
                       "head shape")
@@ -317,10 +318,11 @@ def _get_raw_subject(self):
 
     @on_trait_change('raw_subject')
     def _on_raw_subject_change(self, subject):
-        if subject in self.mri.subject_source.subjects:
-            self.mri4.subject = subject
-        elif 'fsaverage' in self.mri.subject_source.subjects:
-            self.mri.subject = 'fsaverage'
+        if self.guess_mri_subject:
+            if subject in self.mri.subject_source.subjects:
+                self.mri.subject = subject
+            elif 'fsaverage' in self.mri.subject_source.subjects:
+                self.mri.subject = 'fsaverage'
 
     def omit_hsp_points(self, distance=0, reset=False):
         """Exclude head shape points that are far away from the MRI head.
@@ -1107,42 +1109,40 @@ def _make_view(tabbed=False, split=False, scene_width=500):
     view : traits View
         View object for the CoregFrame.
     """
-    view_options = VGroup(Item('headview', style='custom'), 'view_options',
-                          show_border=True, show_labels=False, label='View')
-
-    scene = VGroup(Item('scene', show_label=False,
-                        editor=SceneEditor(scene_class=MayaviScene),
-                        dock='vertical', width=scene_width),
-                   view_options)
-
-    data_panel = VGroup(VGroup(Item('subject_panel', style='custom'),
-                               label="MRI Subject", show_border=True,
-                               show_labels=False),
-                        VGroup(Item('lock_fiducials', style='custom',
-                                    editor=EnumEditor(cols=2,
-                                                      values={False: '2:Edit',
-                                                              True: '1:Lock'}),
-                                    enabled_when='fid_ok'),
-                               HGroup('hsp_always_visible',
-                                      Label("Always Show Head Shape Points"),
-                                      show_labels=False),
-                               Item('fid_panel', style='custom'),
-                               label="MRI Fiducials", show_border=True,
-                               show_labels=False),
-                        VGroup(Item('raw_src', style="custom"),
-                               HGroup(Item('distance', show_label=True),
-                                      'omit_points', 'reset_omit_points',
-                                      show_labels=False),
-                               Item('omitted_info', style='readonly',
-                                    show_label=False),
-                               label='Head Shape Source (Raw/Epochs/Evoked)',
-                               show_border=True, show_labels=False),
-                        show_labels=False, label="Data Source")
-
-    coreg_panel = VGroup(Item('coreg_panel', style='custom'),
-                         label="Coregistration", show_border=True,
-                         show_labels=False,
-                         enabled_when="fid_panel.locked")
+    view_options = VGroup(
+        Item('headview', style='custom'), 'view_options', show_border=True,
+        show_labels=False, label='View')
+
+    scene = VGroup(
+        Item('scene', show_label=False,
+             editor=SceneEditor(scene_class=MayaviScene),
+             dock='vertical', width=scene_width), view_options)
+
+    data_panel = VGroup(
+        VGroup(Item('subject_panel', style='custom'), label="MRI Subject",
+               show_border=True, show_labels=False),
+        VGroup(Item('lock_fiducials', style='custom',
+                    editor=EnumEditor(cols=2, values={False: '2:Edit',
+                                                      True: '1:Lock'}),
+                    enabled_when='fid_ok'),
+               HGroup('hsp_always_visible',
+                      Label("Always Show Head Shape Points"),
+                      show_labels=False),
+               Item('fid_panel', style='custom'),
+               label="MRI Fiducials",  show_border=True, show_labels=False),
+        VGroup(Item('raw_src', style="custom"),
+               HGroup('guess_mri_subject',
+                      Label('Guess MRI Subject from File Name'),
+                      show_labels=False),
+               HGroup(Item('distance', show_label=True), 'omit_points',
+                      'reset_omit_points', show_labels=False),
+               Item('omitted_info', style='readonly', show_label=False),
+               label='Head Shape Source (Raw/Epochs/Evoked)', show_border=True,
+               show_labels=False), show_labels=False, label="Data Source")
+
+    coreg_panel = VGroup(
+        Item('coreg_panel', style='custom'), label="Coregistration",
+        show_border=True, show_labels=False, enabled_when="fid_panel.locked")
 
     if split:
         main_layout = 'split'
@@ -1187,6 +1187,7 @@ class CoregFrame(HasTraits):
     fid_panel = Instance(FiducialsPanel)
     coreg_panel = Instance(CoregPanel)
     raw_src = DelegatesTo('model', 'hsp')
+    guess_mri_subject = DelegatesTo('model')
 
     # Omit Points
     distance = Float(5., label="Distance [mm]", desc="Maximal distance for "
@@ -1238,8 +1239,8 @@ def _coreg_panel_default(self):
     def _headview_default(self):
         return HeadViewController(scene=self.scene, system='RAS')
 
-    def __init__(self, raw=None, subject=None,
-                 subjects_dir=None):  # noqa: D102
+    def __init__(self, raw=None, subject=None, subjects_dir=None,
+                 guess_mri_subject=None):  # noqa: D102
         super(CoregFrame, self).__init__()
 
         subjects_dir = get_subjects_dir(subjects_dir)
@@ -1249,6 +1250,9 @@ def __init__(self, raw=None, subject=None,
         if subject is not None:
             self.model.mri.subject = subject
 
+        if guess_mri_subject is not None:
+            self.guess_mri_subject = guess_mri_subject
+
         if raw is not None:
             self.model.hsp.file = raw
 


Test patch: