populse / populse_mia

Multiparametric Image Analysis
Other
10 stars 9 forks source link

[Controller] Exclusive nipype parameters cause Mia to crash if set at the same time. #316

Closed servoz closed 11 months ago

servoz commented 11 months ago

If the user makes a mistake and declares two mutually exclusive parameters, Mia crashes. We need to catch the exception and not crash.

To reproduce: -1 load a project with a ant.ni, deformation_file. 2- in Pipeline Manager, drag and drop the spm.Normalize12 brick in the nipype library (not the one coming from mia_processes). 3- right click on the brick then "Export all unconnected plugs" 4- click on the inputs brick then in the controller gui (right part of the PipelineManger) click Filter and define for image_to_align the anat.ni then for deformation_file the deformation_file.

Mia crash with the executions stack:

Exception occurred in traits notification handler for object: 
affine_regularization_type = <undefined>
apply_to_files = <undefined>
bias_fwhm = <undefined>
bias_regularization = <undefined>
deformation_file = <undefined>
image_to_align = anat.nii
jobtype = estwrite
matlab_cmd = <undefined>
mfile = True
out_prefix = w
paths = <undefined>
sampling_distance = <undefined>
smoothness = <undefined>
tpm = <undefined>
use_mcr = <undefined>
use_v8struct = True
warping_regularization = <undefined>
write_bounding_box = <undefined>
write_interp = <undefined>
write_voxel_sizes = <undefined>
, trait: deformation_file, old value: <undefined>, new value: y_deformation_file.nii
Traceback (most recent call last):
  File "/home/econdami/.local/lib/python3.9/site-packages/traits/trait_notifiers.py", line 524, in _dispatch_change_event
    self.dispatch(handler, *args)
  File "/home/econdami/.local/lib/python3.9/site-packages/traits/trait_notifiers.py", line 486, in dispatch
    handler(*args)
  File "/home/econdami/.local/lib/python3.9/site-packages/nipype-1.8.7.dev0-py3.9.egg/nipype/interfaces/base/specs.py", line 117, in _xor_warn
    raise OSError(msg)
OSError: Input "deformation_file" is mutually exclusive with input "image_to_align", which is already set
Exception occurred in traits notification handler for object: <capsul.process.process.NipypeProcess object at 0x7f4432c48e50>, trait: deformation_file, old value: <undefined>, new value: y_deformation_file.nii
Traceback (most recent call last):
  File "/home/econdami/.local/lib/python3.9/site-packages/traits/trait_notifiers.py", line 524, in _dispatch_change_event
    self.dispatch(handler, *args)
  File "/home/econdami/.local/lib/python3.9/site-packages/traits/trait_notifiers.py", line 486, in dispatch
    handler(*args)
  File "/data/Git_Projects/capsul/capsul/process/nipype_process.py", line 129, in sync_nypipe_traits
    setattr(process_instance._nipype_interface.inputs,
  File "/home/econdami/.local/lib/python3.9/site-packages/traits/trait_notifiers.py", line 478, in __call__
    self.notify_listener(self, object, trait_name, old, new)
  File "/home/econdami/.local/lib/python3.9/site-packages/traits/trait_notifiers.py", line 552, in _notify_method_listener
    self._dispatch_change_event(
  File "/home/econdami/.local/lib/python3.9/site-packages/traits/trait_notifiers.py", line 532, in _dispatch_change_event
    handle_exception(object, trait_name, old, new)
  File "/home/econdami/.local/lib/python3.9/site-packages/traits/trait_notifiers.py", line 149, in _handle_exception
    raise excp
  File "/home/econdami/.local/lib/python3.9/site-packages/traits/trait_notifiers.py", line 524, in _dispatch_change_event
    self.dispatch(handler, *args)
  File "/home/econdami/.local/lib/python3.9/site-packages/traits/trait_notifiers.py", line 486, in dispatch
    handler(*args)
  File "/home/econdami/.local/lib/python3.9/site-packages/nipype-1.8.7.dev0-py3.9.egg/nipype/interfaces/base/specs.py", line 117, in _xor_warn
    raise OSError(msg)
OSError: Input "deformation_file" is mutually exclusive with input "image_to_align", which is already set

Exception hooking in progress ...

Clean up before closing mia done ...

Traceback (most recent call last):
  File "/data/Git_Projects/soma-base/python/soma/qt_gui/controls/File.py", line 254, in update_controller
    setattr(controller_widget.controller, control_name,
  File "/home/econdami/.local/lib/python3.9/site-packages/traits/trait_notifiers.py", line 478, in __call__
    self.notify_listener(self, object, trait_name, old, new)
  File "/home/econdami/.local/lib/python3.9/site-packages/traits/trait_notifiers.py", line 560, in _notify_function_listener
    self._dispatch_change_event(
  File "/home/econdami/.local/lib/python3.9/site-packages/traits/trait_notifiers.py", line 532, in _dispatch_change_event
    handle_exception(object, trait_name, old, new)
  File "/home/econdami/.local/lib/python3.9/site-packages/traits/trait_notifiers.py", line 149, in _handle_exception
    raise excp
  File "/home/econdami/.local/lib/python3.9/site-packages/traits/trait_notifiers.py", line 524, in _dispatch_change_event
    self.dispatch(handler, *args)
  File "/home/econdami/.local/lib/python3.9/site-packages/traits/trait_notifiers.py", line 486, in dispatch
    handler(*args)
  File "/data/Git_Projects/capsul/capsul/process/nipype_process.py", line 129, in sync_nypipe_traits
    setattr(process_instance._nipype_interface.inputs,
  File "/home/econdami/.local/lib/python3.9/site-packages/traits/trait_notifiers.py", line 478, in __call__
    self.notify_listener(self, object, trait_name, old, new)
  File "/home/econdami/.local/lib/python3.9/site-packages/traits/trait_notifiers.py", line 552, in _notify_method_listener
    self._dispatch_change_event(
  File "/home/econdami/.local/lib/python3.9/site-packages/traits/trait_notifiers.py", line 532, in _dispatch_change_event
    handle_exception(object, trait_name, old, new)
  File "/home/econdami/.local/lib/python3.9/site-packages/traits/trait_notifiers.py", line 149, in _handle_exception
    raise excp
  File "/home/econdami/.local/lib/python3.9/site-packages/traits/trait_notifiers.py", line 524, in _dispatch_change_event
    self.dispatch(handler, *args)
  File "/home/econdami/.local/lib/python3.9/site-packages/traits/trait_notifiers.py", line 486, in dispatch
    handler(*args)
  File "/home/econdami/.local/lib/python3.9/site-packages/nipype-1.8.7.dev0-py3.9.egg/nipype/interfaces/base/specs.py", line 117, in _xor_warn
    raise OSError(msg)
OSError: Input "deformation_file" is mutually exclusive with input "image_to_align", which is already set
Exception occurred in traits notification handler for object: 
affine_regularization_type = <undefined>
apply_to_files = <undefined>
bias_fwhm = <undefined>
bias_regularization = <undefined>
deformation_file = <undefined>
image_to_align = /data/IRM/projects_mia/test/data/raw_data/alej170316_test24042018-IRMFonct_+perfusion-2016-03-17083444-01-T13DSENSE-T1TFE-000425_000.nii
jobtype = estwrite
matlab_cmd = <undefined>
mfile = True
out_prefix = w
paths = <undefined>
sampling_distance = <undefined>
smoothness = <undefined>
tpm = <undefined>
use_mcr = <undefined>
use_v8struct = True
warping_regularization = <undefined>
write_bounding_box = <undefined>
write_interp = <undefined>
write_voxel_sizes = <undefined>
, trait: deformation_file, old value: <undefined>, new value: /data/IRM/projects_mia/test/data/raw_data/alej170316_test24042018-IRMFonct_+perfusion-2016-03-17083444-00-BOLD_CVR_7_53sl_ModeratePNSSENSE-FEEPI-001212_000.nii
Traceback (most recent call last):
  File "/home/econdami/.local/lib/python3.9/site-packages/traits/trait_notifiers.py", line 524, in _dispatch_change_event
    self.dispatch(handler, *args)
  File "/home/econdami/.local/lib/python3.9/site-packages/traits/trait_notifiers.py", line 486, in dispatch
    handler(*args)
  File "/home/econdami/.local/lib/python3.9/site-packages/nipype-1.8.7.dev0-py3.9.egg/nipype/interfaces/base/specs.py", line 117, in _xor_warn
    raise OSError(msg)
OSError: Input "deformation_file" is mutually exclusive with input "image_to_align", which is already set
Exception occurred in traits notification handler for object: <capsul.process.process.NipypeProcess object at 0x7fed152686d0>, trait: deformation_file, old value: <undefined>, new value: /data/IRM/projects_mia/test/data/raw_data/alej170316_test24042018-IRMFonct_+perfusion-2016-03-17083444-00-BOLD_CVR_7_53sl_ModeratePNSSENSE-FEEPI-001212_000.nii
Traceback (most recent call last):
  File "/home/econdami/.local/lib/python3.9/site-packages/traits/trait_notifiers.py", line 524, in _dispatch_change_event
    self.dispatch(handler, *args)
  File "/home/econdami/.local/lib/python3.9/site-packages/traits/trait_notifiers.py", line 486, in dispatch
    handler(*args)
  File "/data/Git_Projects/capsul/capsul/process/nipype_process.py", line 129, in sync_nypipe_traits
    setattr(process_instance._nipype_interface.inputs,
  File "/home/econdami/.local/lib/python3.9/site-packages/traits/trait_notifiers.py", line 478, in __call__
    self.notify_listener(self, object, trait_name, old, new)
  File "/home/econdami/.local/lib/python3.9/site-packages/traits/trait_notifiers.py", line 552, in _notify_method_listener
    self._dispatch_change_event(
  File "/home/econdami/.local/lib/python3.9/site-packages/traits/trait_notifiers.py", line 532, in _dispatch_change_event
    handle_exception(object, trait_name, old, new)
  File "/home/econdami/.local/lib/python3.9/site-packages/traits/trait_notifiers.py", line 149, in _handle_exception
    raise excp
  File "/home/econdami/.local/lib/python3.9/site-packages/traits/trait_notifiers.py", line 524, in _dispatch_change_event
    self.dispatch(handler, *args)
  File "/home/econdami/.local/lib/python3.9/site-packages/traits/trait_notifiers.py", line 486, in dispatch
    handler(*args)
  File "/home/econdami/.local/lib/python3.9/site-packages/nipype-1.8.7.dev0-py3.9.egg/nipype/interfaces/base/specs.py", line 117, in _xor_warn
    raise OSError(msg)
OSError: Input "deformation_file" is mutually exclusive with input "image_to_align", which is already set
Exception occurred in traits notification handler for object: <capsul.pipeline.pipeline.Pipeline object at 0x7fed1550c220>, trait: deformation_file, old value: <undefined>, new value: /data/IRM/projects_mia/test/data/raw_data/alej170316_test24042018-IRMFonct_+perfusion-2016-03-17083444-00-BOLD_CVR_7_53sl_ModeratePNSSENSE-FEEPI-001212_000.nii
Traceback (most recent call last):
  File "/home/econdami/.local/lib/python3.9/site-packages/traits/trait_notifiers.py", line 524, in _dispatch_change_event
    self.dispatch(handler, *args)
  File "/home/econdami/.local/lib/python3.9/site-packages/traits/trait_notifiers.py", line 486, in dispatch
    handler(*args)
  File "/data/Git_Projects/soma-base/python/soma/utils/functiontools.py", line 90, in __call__
    return self.func(*(self.args + args), **merged_kwargs)
  File "/data/Git_Projects/capsul/capsul/pipeline/pipeline_nodes.py", line 234, in _value_callback
    dest_node.set_plug_value(
  File "/data/Git_Projects/capsul/capsul/pipeline/pipeline_nodes.py", line 797, in set_plug_value
    self.process.set_parameter(plug_name, value, protected)
  File "/data/Git_Projects/capsul/capsul/process/process.py", line 1067, in set_parameter
    setattr(self, name, value)
  File "/home/econdami/.local/lib/python3.9/site-packages/traits/trait_notifiers.py", line 478, in __call__
    self.notify_listener(self, object, trait_name, old, new)
  File "/home/econdami/.local/lib/python3.9/site-packages/traits/trait_notifiers.py", line 560, in _notify_function_listener
    self._dispatch_change_event(
  File "/home/econdami/.local/lib/python3.9/site-packages/traits/trait_notifiers.py", line 532, in _dispatch_change_event
    handle_exception(object, trait_name, old, new)
  File "/home/econdami/.local/lib/python3.9/site-packages/traits/trait_notifiers.py", line 149, in _handle_exception
    raise excp
  File "/home/econdami/.local/lib/python3.9/site-packages/traits/trait_notifiers.py", line 524, in _dispatch_change_event
    self.dispatch(handler, *args)
  File "/home/econdami/.local/lib/python3.9/site-packages/traits/trait_notifiers.py", line 486, in dispatch
    handler(*args)
  File "/data/Git_Projects/capsul/capsul/process/nipype_process.py", line 129, in sync_nypipe_traits
    setattr(process_instance._nipype_interface.inputs,
  File "/home/econdami/.local/lib/python3.9/site-packages/traits/trait_notifiers.py", line 478, in __call__
    self.notify_listener(self, object, trait_name, old, new)
  File "/home/econdami/.local/lib/python3.9/site-packages/traits/trait_notifiers.py", line 552, in _notify_method_listener
    self._dispatch_change_event(
  File "/home/econdami/.local/lib/python3.9/site-packages/traits/trait_notifiers.py", line 532, in _dispatch_change_event
    handle_exception(object, trait_name, old, new)
  File "/home/econdami/.local/lib/python3.9/site-packages/traits/trait_notifiers.py", line 149, in _handle_exception
    raise excp
  File "/home/econdami/.local/lib/python3.9/site-packages/traits/trait_notifiers.py", line 524, in _dispatch_change_event
    self.dispatch(handler, *args)
  File "/home/econdami/.local/lib/python3.9/site-packages/traits/trait_notifiers.py", line 486, in dispatch
    handler(*args)
  File "/home/econdami/.local/lib/python3.9/site-packages/nipype-1.8.7.dev0-py3.9.egg/nipype/interfaces/base/specs.py", line 117, in _xor_warn
    raise OSError(msg)
OSError: Input "deformation_file" is mutually exclusive with input "image_to_align", which is already set

Exception hooking in progress ...

Clean up before closing mia done ...

Traceback (most recent call last):
  File "/data/Git_Projects/populse_mia/populse_mia/user_interface/pipeline_manager/node_controller.py", line 1680, in update_plug_value_from_filter
    self.update_plug_value("in", plug_name, pipeline, value_type, res)
  File "/data/Git_Projects/populse_mia/populse_mia/user_interface/pipeline_manager/node_controller.py", line 1612, in update_plug_value
    pipeline.nodes[node_name].set_plug_value(plug_name, new_value)
  File "/data/Git_Projects/capsul/capsul/pipeline/pipeline_nodes.py", line 797, in set_plug_value
    self.process.set_parameter(plug_name, value, protected)
  File "/data/Git_Projects/capsul/capsul/process/process.py", line 1067, in set_parameter
    setattr(self, name, value)
  File "/home/econdami/.local/lib/python3.9/site-packages/traits/trait_notifiers.py", line 478, in __call__
    self.notify_listener(self, object, trait_name, old, new)
  File "/home/econdami/.local/lib/python3.9/site-packages/traits/trait_notifiers.py", line 560, in _notify_function_listener
    self._dispatch_change_event(
  File "/home/econdami/.local/lib/python3.9/site-packages/traits/trait_notifiers.py", line 532, in _dispatch_change_event
    handle_exception(object, trait_name, old, new)
  File "/home/econdami/.local/lib/python3.9/site-packages/traits/trait_notifiers.py", line 149, in _handle_exception
    raise excp
  File "/home/econdami/.local/lib/python3.9/site-packages/traits/trait_notifiers.py", line 524, in _dispatch_change_event
    self.dispatch(handler, *args)
  File "/home/econdami/.local/lib/python3.9/site-packages/traits/trait_notifiers.py", line 486, in dispatch
    handler(*args)
  File "/data/Git_Projects/soma-base/python/soma/utils/functiontools.py", line 90, in __call__
    return self.func(*(self.args + args), **merged_kwargs)
  File "/data/Git_Projects/capsul/capsul/pipeline/pipeline_nodes.py", line 234, in _value_callback
    dest_node.set_plug_value(
  File "/data/Git_Projects/capsul/capsul/pipeline/pipeline_nodes.py", line 797, in set_plug_value
    self.process.set_parameter(plug_name, value, protected)
  File "/data/Git_Projects/capsul/capsul/process/process.py", line 1067, in set_parameter
    setattr(self, name, value)
  File "/home/econdami/.local/lib/python3.9/site-packages/traits/trait_notifiers.py", line 478, in __call__
    self.notify_listener(self, object, trait_name, old, new)
  File "/home/econdami/.local/lib/python3.9/site-packages/traits/trait_notifiers.py", line 560, in _notify_function_listener
    self._dispatch_change_event(
  File "/home/econdami/.local/lib/python3.9/site-packages/traits/trait_notifiers.py", line 532, in _dispatch_change_event
    handle_exception(object, trait_name, old, new)
  File "/home/econdami/.local/lib/python3.9/site-packages/traits/trait_notifiers.py", line 149, in _handle_exception
    raise excp
  File "/home/econdami/.local/lib/python3.9/site-packages/traits/trait_notifiers.py", line 524, in _dispatch_change_event
    self.dispatch(handler, *args)
  File "/home/econdami/.local/lib/python3.9/site-packages/traits/trait_notifiers.py", line 486, in dispatch
    handler(*args)
  File "/data/Git_Projects/capsul/capsul/process/nipype_process.py", line 129, in sync_nypipe_traits
    setattr(process_instance._nipype_interface.inputs,
  File "/home/econdami/.local/lib/python3.9/site-packages/traits/trait_notifiers.py", line 478, in __call__
    self.notify_listener(self, object, trait_name, old, new)
  File "/home/econdami/.local/lib/python3.9/site-packages/traits/trait_notifiers.py", line 552, in _notify_method_listener
    self._dispatch_change_event(
  File "/home/econdami/.local/lib/python3.9/site-packages/traits/trait_notifiers.py", line 532, in _dispatch_change_event
    handle_exception(object, trait_name, old, new)
  File "/home/econdami/.local/lib/python3.9/site-packages/traits/trait_notifiers.py", line 149, in _handle_exception
    raise excp
  File "/home/econdami/.local/lib/python3.9/site-packages/traits/trait_notifiers.py", line 524, in _dispatch_change_event
    self.dispatch(handler, *args)
  File "/home/econdami/.local/lib/python3.9/site-packages/traits/trait_notifiers.py", line 486, in dispatch
    handler(*args)
  File "/home/econdami/.local/lib/python3.9/site-packages/nipype-1.8.7.dev0-py3.9.egg/nipype/interfaces/base/specs.py", line 117, in _xor_warn
    raise OSError(msg)
OSError: Input "deformation_file" is mutually exclusive with input "image_to_align", which is already set

Maybe the best (simple) fix will be to catch (and just print the message exception in the stdout) ? Good candidate in update_plug_value_from_filter() for V1 controller (mia) and update_controller() for V2 (soma).

I'll do it as soon as possible for the V1 GUI.

@denisri for V2, I can see a solution. In update_controller() we only catch the traits.TraitError class. Would there be a issue catching (traits.TraitError, OSError) [l257 becomes except (traits.TraitError, OSError) as e:] ??? because nipye raises an OSError error if two mutually exclusive parameters are declared at the same time. If this causes a regression, we can see if we can catch the exception in populse_mia at the same time.

denisri commented 11 months ago

I'm OK to modify update_controller(), no problem. Are you doing it, or do you want me to do it ?

servoz commented 11 months ago

I can do it. But I've just tested the idea, there's no crash, but the value is modified in this case... that's not exactly what we want.

We want 1- to catch the exception, 2- inform the user (by printing in stdout the message sent by nipype for example), and 3- reset to the old value. Here, the third point doesn't work... I need to examine the codes. I'll have a look at V2 and V1.

denisri commented 11 months ago

This new issue is probably not linked to the graphical interface of Controller but the way exclusive traits are handled in Controller...?

denisri commented 11 months ago

The exception is raised from File "/data/Git_Projects/capsul/capsul/process/nipype_process.py", line 129, in sync_nypipe_traits, which is a callback set on Capsul traits value changes, so if there is an exception there (in setting the nipype trait value), resetting the Capsul trait value should probably be done there before re-raising the exception.

servoz commented 11 months ago

Sorry I was on another project till now

This new issue is probably not linked to the graphical interface of Controller but the way exclusive traits are handled in Controller...?

Yes, that's right, it's more about how the controller handles the data than the GUI.

The exception is raised from File "/data/Git_Projects/capsul/capsul/process/nipype_process.py", line 129, in sync_nypipe_traits, which is a callback set on Capsul traits value changes, so if there is an exception there (in setting the nipype trait value), resetting the Capsul trait value should probably be done there before re-raising the exception.

You're right, the case is more complicated than simply adding the error class raised by nipype (which is what I thought at first) because there's a succession of callbacks (the capsul one you're talking about and the nipype one for managing mutually exclusive parameters). I confess I haven't yet found a way to correct the bug, as I didn't have much time this afternoon.

denisri commented 11 months ago

I have pushed an attempt to fix this, but I haven't tested it (I'm also on another job). Can you give it a try when you have a minute ?

servoz commented 11 months ago

Due to lack of time, I may have read what you wrote above a little too quickly... Indeed, we'll also have to reset the old value everywhere (controller and synchronization between values in the nipype and capsul processes!!!!). Your fix is effective @denisri , thank you! I'm pushing the change in soma and I think this ticket can now be closed.

servoz commented 11 months ago

Fixed for V1 and V2.