How to run .m script using spm standalone with mcr? any example?

Hi,

I was trying to run a matlab script that uses some functions from spm through nipype interface. That worked fine when adding spm path in the matlab script. But I could not find a way to run a script in a similar way where a matlab script is run from a nipype interface using only standalone spm and MCR. If I built a custom interface similar to the one used for a simple command line, it also works (by just wrapping the _cmd = run_spm12.sh mcr script myscriptfile.m). But I wonder if there is a better way to run a .m script using compiled spm and mcr?
I can get the version printed when I use this example:

from nipype.interfaces import spm
matlab_cmd = ā€˜/path/to/run_spm8.sh /path/to/Compiler_Runtime/v713/ scriptā€™
spm.SPMCommand.set_mlab_paths(matlab_cmd=matlab_cmd, use_mcr=True)
spm.SPMCommand().version

But how can I load my .m file if I want a node in the workflow?
Can anyone show me a simple example where I can load my spm script?
Thanks a lot,

Best regards,

ā€“
Shahid.

1 Like

Are you still having problem with your script? I donā€™t have any example for you and I actually donā€™t code in matlab, but I can try to help you if you provide me some simple matlab script and example how you would like to use it with nipype.

The general question is if it wouldnā€™t be easier to rewrite the script in python and use nipype to call spm functions?

Hi,

Thanks for your reply. Yes I still didnā€™t find a similar way to call a matlab script that has spm functions but to exectute them using MCR. For example you can have a look at this documentation page:
[1] http://nipype.readthedocs.io/en/latest/devel/matlab_interface_devel.html
Here the matlab scripts can be wrapped inside a custome interface.
if you want to use spm functions inside your matlab scripts, spm should be in matlab path.

But the other way to use spm from nipype using standalone compiled spm and MCR, you can use the spm interfaces
like spmnode=pe.Node(interface=spm.Smooth()ā€¦) as shown here:
[2] http://nipype.readthedocs.io/en/latest/users/spmmcr.html

And I wonder if there is also a similar way to load a matlab script as in [1] above but use standalone spm and MCR?

Best regards,

ā€“
Shahid.

Hi Shahid,

could you solve this issue in the meantime? If yes, maybe you could provide an answer to your question? I am struggling with the exact same problemā€¦

I found a lot of links around this topic but still couldnā€™t manage to set up a simple dummy script (e.g. run a .m-script using MCR that simply prints ā€˜helloā€™). Specifically, I am using Michael Notterā€™s nipype_tutorial container that contains the precompiled MATLAB version. In this container, the application file is saved under '/opt/matlabmcr-2010a/v713/bin/matlab'

Thereā€™s one similar neurostars post (which also hasnā€™t received an answer) and one post on the mailing list. In this github issue, there is some code which tells how to set up a basic MatlabCommand class but I couldnā€™t integrate this information to come up with a working example. Finally, on this page thereā€™s a description of how to ā€˜tellā€™ the class where it can find MATLAB and I guess thatā€™s also the crucial part that is missing currently in my code.

I always get this message: OSError: No command "matlab" found on host 2e1d943f4729. Please check that the corresponding package is installed.

Hi Johannes,

Yes, i have solved the issue to use compiled spm12 with MCR inside nipype. First you need to compile the SPM using MCC and then you have to use that version MCR.
So if you have a .m script that uses functionalities from SPM, first you need to test it if it works correctly outside nipype as:
~/spm12_deployed/run_spm12.sh ~/MCR2017b/v93 script myscript.m
If myscirpt.m completes without errors, then you need to make your own simple interface in nipype. Inside your custom nipype interface you use the _cmd as:
_cmd = ā€™ script spmscript.mā€™

or let me know if you need further help to create a nipype custome interface.

one more thing, if you dont use the compiled SPM or any functions from SPM, then you can also compile your matlab code first and then use the run_mycode.sh as the _cmd of your interface and nipype will set the arguments from the inputs_spec.

Hi Shahid,

thanks for the response! So in my case, I would be generally interested to know how to execute MATLAB code via nipype inside a docker container (in my case, the nipype_tutorial docker container). I do not specifically need SPM commands to run.

In the GitHub Issue that I posted, the OP just described such a ā€˜simple caseā€™ (run a matlab script that just ā€œcomputes the area of a polygonā€). The OP received the answer here but I donā€™t know what kind of arguments I have to provide to replicate this exampleā€¦For example what do I have to write for matlab.inputs.paths = ['/some/path/here', '/you/can/add/many/paths']?

So I followed your instructions and wrote just a simple toy-script test.m:

fid = fopen('test.txt','wt');
fprintf(fid, 'foobar');
fclose(fid);

Then I ran the following line of code from jupyter-notebook:

! /opt/spm12-r7219/run_spm12.sh /opt/matlabmcr-2010a/v713/ script test.m

This worked and saved the file text.txt with 'foobar' inside my working directory. So generally it should be possible to run a .m script using MCR on my machine. But from here on I donā€™t know how to continue. Specifically for my current problem, I would like to write a Node that takes in a Bunch object from Python and writes its values to a .mat fileā€¦

So I guess this should be feasible by somehow using the MatlabCommand interface and by providing this interface with the information on where it can find MCR (/opt/matlabmcr-2010a/v713/ in my case)?

alright, if you dont need any functions from spm then you also dont need to use the standalone/compiled version of spm. But you can compile your .m script to make it as a standalone application e.g:
./run_mymatlabmain.sh MCR/v713 [args]
as similar as the [script or batch] was an arg for the run_spm12.sh compiled spm.
so i always use these two ways to make nipype nodes in my wf.

e.g i have a node in my wf as:
csrecon = pe.Node(interface=CSRECON(), name=ā€˜csreconā€™)
csrecon.n_procs = poolsize
csrecon.inputs.csrecon_path = csrecon_path
csrecon.inputs.mcr_path = mcr_path
csrecon.inputs.poolsize = poolsize

the csrecon interface is defined in a file as:

class CSRECONInputSpec(CommandLineInputSpec):
poolsize = traits.Int(ā€˜Matlab parallel pool sizeā€™, argstr=ā€™%dā€™, position=8,mandatory=True)
csrecon_path = File(exists=True, desc=ā€˜FileName of CSRecon exe script (run_mainCS.sh)ā€™)
mcr_path = Directory(exists=True, desc=ā€˜MCR path (/path/to/compiler_Runtime/v93/ā€™)

class CSRECON(CommandLine):
input_spec = CSRECONInputSpec
output_spec = CSRECONOutputSpec
_cmd = ā€˜run_main_CS.shā€™
def init(self, **inputs):
return super(CSRECON, self).init(**inputs)

def _run_interface(self, runtime):
    
    self._cmd = self.inputs.csrecon_path + ' ' + self.inputs.mcr_path + ' ' + os.getcwd()
    runtime = super(CSRECON, self)._run_interface(runtime)
    if runtime.stderr:
       self.raise_exception(runtime)
    return runtime

hope it helps youā€¦

Hi Shahid, sorry for the late answer. I was able to solve my particular problem by simply using scipy.io.savemat thus I didnā€™t need a MATLAB script anymore to solve my problem.

I think your code is missing the specification of CSRECONOutputSpec? At least I get an error on that when trying to run your code:

from nipype.interfaces.base import traits
from nipype.interfaces.base import TraitedSpec
from nipype.interfaces.matlab import MatlabCommand, MatlabInputSpec
from nipype.interfaces.base import CommandLineInputSpec,CommandLine,File,Directory

class CSRECONInputSpec(CommandLineInputSpec):
    poolsize = traits.Int('Matlab parallel pool size',argstr='%d',position=8,mandatory=True)
    csrecon_path = File(exists=True,desc='FileName of CSRecon exe script (run_mainCS.sh)')
    mcr_path = Directory(exists=True, desc='MCR path (/path/to/compiler_Runtime/v93/')

class CSRECON(CommandLine):
    input_spec = CSRECONInputSpec
    output_spec = CSRECONOutputSpec
    _cmd = 'run_main_CS.sh'
    
    def init(self, **inputs):
        return super(CSRECON, self).init(**inputs)

    def _run_interface(self, runtime):

        self._cmd = self.inputs.csrecon_path + ' ' + self.inputs.mcr_path + ' ' + os.getcwd()
        runtime = super(CSRECON, self)._run_interface(runtime)
        if runtime.stderr:
           self.raise_exception(runtime)
        return runtime

One last question regarding ā€œBut you can compile your .m script to make it as a standalone applicationā€: Do you mean using MATLAB Compiler - MATLAB to do that?

Hi Johannes, yes you are right, the outputspec is missing, that can be added similar to the inputspecā€¦
yes, to compile you need MATLAB Compiler (mcc), to get your matlab scritps into a standalone application that would only require matlab runtime (MCR) of the same version thru which you compiled your matlab code.

1 Like

Hi, I am working on spm12 and I want to run my scripts using spm12 functions on a Linux server using commands. I am facing some errors. Do you have any idea to run these scripts on a Linux server using the MCR installer.

Hi,
Have you got the standalone version of spm12? if yes, then you can run your .m scripts with spm12 and MCR as one of the following commands:

./run_spm12.sh /path/to/MCR/vX script your_script.m

your_script.m should be calling the spm functions.
cheersā€¦

will it work for the Linux server? without GUI

Where to got spm12 standalone for R2018b mcr. If not available can you please guide me how to create SPM12 Standalone Application?

A version of SPM12 standalone for MATLAB Runtime R2019b is available here (temporary link). The corresponding MATLAB Runtime itself can be downloaded here.
If you want to compile SPM yourself, instructions are available here (third item in the list).

Yes, it should, as mentioned by @mohammad.shahid. Could you copy-paste here the error messages you observed?

Ok. First, let me explain to you what I want actually. I have created a script that takes data and spm12 path and calls a function that is also created by me names as preprocessing. In this function, I have called spm12 functions for preprocessing of data. I have created a standalone application as ssh to run these scripts on the Linux server and used the spm12 standalone version. Itā€™s showing errors like this:

This is the error after following this method

Thank you - this is useful.

The error about cfg_getfile indicates that you compiled SPM yourself without relying on spm_make_standalone: using this function should solve the issue for you.

Note that when using the syntax script your_script.m, you can pass parameters from the command line and they will be available from a variable called inputs (a cell array) in your script. This means you could pass the data directory and the subject index from the command line with any interactive step. Also you shouldnā€™t have to provide the location of the SPM installation - if you need this information from a script, using spm('Dir').

Finally, concerning the error about spm_preprocessing: this is not an SPM function so, if it is a function (and not a script), make sure you include it in your SPM compilation.

I have used spm_make_standalone function for SPM compilation and there was an option to add required files to runā€¦
What to add there or need to left that empty??
I want to remove the error about cfg_getfile