Run Freesurfer command from Slicer extension

Hi, I’m developing an Extension in python to anonymize MRIs and I need to use some Freesurfer commands (mri_info, mris_convert and mri_watershed).

Is there a way to run Freesurfer commands from inside a Slicer Extension?

I’m using subprocess to perform the function calls but I get an error “non-zero exit status -6”. I tried the solution showed in Subprocess call in Python interpreter results in memory corruption, adding the binaries directory to the path as done in Elastix, and also using slicer.utils.startupEnvironment() but I can’t make it work.

Here is an example code:

...
def getFsEnv(self):
    fsBinDir = '/path/to/binaries'
    fsEnv = os.environ.copy()
    fsEnv["PATH"] = fsBinDir + os.pathsep + fsEnv["PATH"] if fsEnv.get("PATH") else fsBinDir

...
fsEnv=self.getFsEnv()
subprocess.check_output(shlex.split('mri_info /path/to/file.mgz'), env=fsEnv)

I’ve also tried with subprocess.Popen(). In this case I think it starts and then stops:

logfile=open("filename", "w")
subprocess.Popen(shlex.split('mri_watershed -useSRAS -surf /path/ /file.mgz /path'), env=fsEnv, stdout=logfile)
logfile.close()

If i do like that, I see the beginning of the output on the logfile (only 2 lines) but the process doesn’t continue (i.e. the surfaces are not created and htop shows no cpu usage). If I use subprocess.check_call() I also get the -6 error.

Any help would be greatly appreaciated, thanks.

Operating system: OSX 10.15.6
Slicer version: 4.10.2
Expected behavior: Using subprocess to run Freesurfer commands
Actual behavior: “non-zero exit status -6”

Probably the freesurfer commands use some of the same dynamic libraries as Slicer and this causes a conflict. To resolve this, run the external process in the startup environment (instead of Slicer’s environment), as shown here: https://www.slicer.org/wiki/Documentation/Nightly/ScriptRepository#Run_process_in_default_environment

Thanks for your reply. I had tried using slicer.util.startupEnvironment() but it produces the same error.

For example:

subprocess.check_output(shlex.split('/Applications/freesurfer/bin/mri_info /filename.mgz'),
                        env=slicer.util.startupEnvironment())

I also tried adding the whole folder with binaries to the startupEnvironment:

slEnv=slicer.util.startupEnvironment()
slEnv['PATH']='/Applications/freesurfer/bin:' + slEnv['PATH']

subprocess.check_output(shlex.split('mri_info /filename.mgz'),
                        env=slEnv)

But I still get the same error. (The example code in the link you provided works without problems)

Thanks again,

Please try with latest Slicer Preview Release.
Also, try the same command from a regular Python3 interpreter to see if the syntax of the call is correct.

You may also use these convenience functions:

proc = slicer.util.launchConsoleProcess(commandLine, useStartupEnvironment=True)
slicer.util.logProcessOutput(proc)

I think I found the key to the problem. Your idea about dynamic libraries was correct.

If I add:

fsEnv['DYLD_LIBRARY_PATH']='/Applications/freesurfer/lib/gcc/lib'

I’m able to run freesurfer commands without problems. I’ll keep studying the problem and add any new insights and a more complete answer here for future reference. Thanks for all your help!

1 Like