Matlab Bridge - module execution error - output list of fiducial points

Operating system:Ubuntu 16.04
Slicer version: 4.10
Expected behavior: output fiducial from Matlab Bridge extension
Actual behavior: error

Hello everybody, I am implementing a Matlab Bridge extension which takes as input:

  1. two fiducial markers
  2. an input mesh

and as output:

  1. a long list of fiducial markers ( which are the 3D coordinates of several paths (up to 10 paths))
  2. an output mesh

I get an error on the first output, whenever I try to include even just one single RAS coordinates point as output. Would you help me understanding what I am missing please?

Just to clarify …my final goal would be to plot these paths using CurveMaker so that I am not sure whether there is also a easier way to save trajectories from Matlab and pass them to Slicer.

thank you very much for any suggestion

Marlene

This is the Matlab Bridge function:

function outputParams  = New_AFT_slicer(inputParams)

mesh = cli_geometryread(inputParams.inputmesh);
fiducials=cli_pointvectordecode(inputParams.fiducials);

start=fiducials(:,2);
target=fiducials(:,1);

[mesh,path]=sheep_skull_margin(start',target');

outputParams.Paths=path; 
cli_pointfilewrite(inputParams.Paths_calc, path);
cli_geometrywrite(inputParams.outputmesh, mesh);

ERROR:

New_AFT_slicer standard error:

Failed to execute Matlab function: New_AFT_slicer, received the following error message: 
ERROR: Command execution failed. Reference to non-existent field 'Paths_calc'.

Error in New_AFT_slicer (line 37)
cli_pointfilewrite(inputParams.Paths_calc, path);

Error in cli_commandserver (line 91)
                response=evalc(cmd);

Error in run (line 91)
evalin('caller', strcat(script, ';'));

This is the XML:

<parameters>
    <label>Inputs</label>
    <description><![CDATA[Inputs for the processing]]></description>
    <geometry fileExtensions=".ply" >
      <label>Input model</label>
      <description><![CDATA[Input triangular surface mesh]]></description>
      <longflag>inputmesh</longflag>
      <channel>input</channel>
    </geometry>
    
    
<point multiple="true" coordinateSystem="ras">
      <label>fiducials</label>
      <description><![CDATA[Input volume to be filtered]]></description>
      <longflag>fiducials</longflag>
      <default>0,0,0</default>
      <channel>input</channel>
    </point>

    <label>Output</label>    
    <description><![CDATA[Computed output]]></description>
    <geometry fileExtensions=".ply" >
      <label>Output model</label>
      <description><![CDATA[Transformed triangular surface mesh.]]></description>
      <longflag>outputmesh</longflag>
      <channel>output</channel>
    </geometry>

<point multiple="true" coordinateSystem="ras">
      <label>Paths</label>
      <description><![CDATA[Paths generated]]></description>
      <longflag>Paths_calc</longflag>
      <default>0,0,0</default>
      <channel>output</channel>
    </point>

  </parameters>
</executable>

point element is uses the command-line to pass point coordinates to the module, therefore cannot be used for output parameter. You have to use pointfile element for output point lists instead.

Another way is to use Matlab engine for python, which basically gives you access to your current Matlab session in Slicer. I’ve found it to be easier especially when there’s a lot of back and forth between Matlab and Slicer. You can read more here: https://www.mathworks.com/help/matlab/matlab-engine-for-python.html

Thanks for the suggestion. Slicer’s MatlabBridge was developed many years before Matlab’s Python engine was created - maybe we should promote this new integration approach instead.

How do you pass MRML node content between your Matlab functions and Slicer? Using Python CLI or by implementing a Python scripted module?

By implementing a Python scripted module. From Mathworks: " The matlab Python package provides array classes to represent arrays of MATLAB numeric types as Python variables so that MATLAB arrays can be passed between Python and MATLAB.". Like so:

import matlab.engine
A = matlab.double([[1,2,3,4,5], [6,7,8,9,10]])
print(A)
[[1.0,2.0,3.0,4.0,5.0],[6.0,7.0,8.0,9.0,10.0]]

I haven’t extensively played with passing arrays back and forth since that wasn’t needed in my case, but it looks straight forward. I can put together a simple example if it helps.

Hi Roozbeh,

I had installed Matlab engine for python successfully. However, I can not import it in my module script because the python in Slicer is different from that in the system. So how can use it in my module script?
Thanks!

You need to install Python packages in Slicer’s Python environment (e.g., by running pip_install command in Slicer’s Python console). You can also use MatlabBridge extension to run Matlab functions from Slicer.

What are those Matlab features that you need that are not available in Python packages?

Hi Andras,

Thanks! I followed the instruction (https://www.mathworks.com/help/matlab/matlab-engine-for-python.html) mentioned by @roozbehshams, instead, I run "PythonSlicer setup.py install ". It works finally after I upgraded a lib.

There are some powerful Matlab packages in Lead-DBS and SPM which are not available in Python packages, and I plan to add these packages into my module.

What exactly you had to upgrade? (just to help others who want to follow this approach)

I see. It is very unfortunate that these packages are built on top of closed-source proprietary software. Hopefully they will consider porting their invaluable work to open platforms, until then there is indeed not much else you can do than interface with Matlab.

The error is “/usr/lib/x86_64-linux-gnu/libstdc++.so.6: version ‘GLIBCXX_3.4.22’ not found!

“In my computer there is only GLIBCXX_3.4.20, so I download libstdc++.so.6.0.22 and install it!

1 Like