# Run Freesurfer command from Slicer extension

**URL:** <https://discourse.slicer.org/t/run-freesurfer-command-from-slicer-extension/13504>\
**Category:** Support\
**Created:** [September 16, 2020, 3:41pm UTC](https://discourse.slicer.org/t/run-freesurfer-command-from-slicer-extension/13504 "2020-09-16T15:41:53Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![ezemikulan](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/ezemikulan/32/4850_2.png) [@ezemikulan](https://discourse.slicer.org/u/ezemikulan)\
**Post date:** [September 16, 2020, 3:41pm UTC](https://discourse.slicer.org/t/run-freesurfer-command-from-slicer-extension/13504/1 "2020-09-16T15:41:53Z")

</div>

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](https://discourse.slicer.org/t/subprocess-call-in-python-interpreter-results-in-memory-corruption/919/8), 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:

```auto
...
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:

```auto
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”

---

<div class="post-metadata">

**Author:** ![lassoan](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/lassoan/32/13_2.png) [@lassoan](https://discourse.slicer.org/u/lassoan)\
**Post date:** [September 17, 2020, 1:03am UTC](https://discourse.slicer.org/t/run-freesurfer-command-from-slicer-extension/13504/2 "2020-09-17T01:03:35Z")

</div>

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](https://www.slicer.org/wiki/Documentation/Nightly/ScriptRepository#Run_process_in_default_environment)

---

<div class="post-metadata">

**Author:** ![ezemikulan](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/ezemikulan/32/4850_2.png) [@ezemikulan](https://discourse.slicer.org/u/ezemikulan)\
**Post date:** [September 17, 2020, 10:40am UTC](https://discourse.slicer.org/t/run-freesurfer-command-from-slicer-extension/13504/3 "2020-09-17T10:40:29Z")

</div>

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

For example:

```auto
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:

```auto
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,

---

<div class="post-metadata">

**Author:** ![lassoan](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/lassoan/32/13_2.png) [@lassoan](https://discourse.slicer.org/u/lassoan)\
**Post date:** [September 17, 2020, 11:27am UTC](https://discourse.slicer.org/t/run-freesurfer-command-from-slicer-extension/13504/4 "2020-09-17T11:27:05Z")

</div>

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:

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

```

---

<div class="post-metadata">

**Author:** ![ezemikulan](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/ezemikulan/32/4850_2.png) [@ezemikulan](https://discourse.slicer.org/u/ezemikulan)\
**Post date:** [September 17, 2020, 1:37pm UTC](https://discourse.slicer.org/t/run-freesurfer-command-from-slicer-extension/13504/5 "2020-09-17T13:37:08Z")

</div>

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

If I add:

```auto
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!

---

<div class="post-metadata">

**Author:** ![ezemikulan](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/ezemikulan/32/4850_2.png) [@ezemikulan](https://discourse.slicer.org/u/ezemikulan)\
**Post date:** [April 2, 2021, 9:41am UTC](https://discourse.slicer.org/t/run-freesurfer-command-from-slicer-extension/13504/6 "2021-04-02T09:41:15Z")

</div>

I was able to make it work on both Mac and Linux, here’s what I did:

First I define a function to set up the environment:

```
def getFsEnv(self):
    """Create an environment where executables are added to the path"""
    base_dir = os.path.split(slicer.modules.modulename.path)[0]
    fsBinDir = '%s/Resources/bin:/usr/lib:' % base_dir
    fsEnv = os.environ.copy()
    fsEnv["PATH"] = fsBinDir + os.pathsep + fsEnv["PATH"] if fsEnv.get("PATH") else fsBinDir
    fsEnv['DYLD_LIBRARY_PATH'] = '%s/Resources/lib/gcc/lib' % base_dir
    fsEnv['FREESURFER_HOME'] = '%s/Resources' % base_dir
    return fsEnv

```

Then at the point where I need to call freesurfer’s function I get the environment and run the command using it:

```
import subprocess as sp
import shlex
fsEnv = self.getFsEnv()
command = 'mri_watershed -useSRAS -surf %s/%s %s %s/bems/ws' % (file_dir, base_name, f, file_dir)
p = sp.Popen(shlex.split(command), env=fsEnv, stdout=logfile, stderr=logfile)
p.wait()    

```

For this to work the freesurfer scripts and files required should be included in the right hierarchy or pointed to. For example on the code above I’m adding **‘%s/Resources/lib/gcc/lib’ % base\_dir** to **‘DYLD\_LIBRARY\_PATH’** and defining **‘%s/Resources’ % base\_dir** as **‘FREESURFER\_HOME’**.

The folder structure (including only the files relevant for this topic) in my case looks like this:

> .  
> ├── ModuleName.py  
> ├── ModuleName.pyc  
> ├── CMakeLists.txt  
> ├── Resources  
> │ ├── bin  
> │ │ ├── mri\_info  
> │ │ ├── mri\_watershed  
> │ │ └── mris\_convert  
> │ ├── lib  
> │ │ ├── bem  
> │ │ │ ├── ic0.tri  
> │ │ │ ├── ic1.tri  
> │ │ │ ├── ic2.tri  
> │ │ │ ├── ic3.tri  
> │ │ │ ├── ic4.tri  
> │ │ │ ├── ic5.tri  
> │ │ │ ├── ic6.tri  
> │ │ │ ├── ic7.tri  
> │ │ │ ├── inner\_skull.dat  
> │ │ │ ├── outer\_skin.dat  
> │ │ │ └── outer\_skull.dat  
> │ │ └── gcc  
> │ │ └── lib  
> │ │ ├── libgcc\_s.1.dylib  
> │ │ ├── libgfortran.3.dylib  
> │ │ ├── libgomp.1.dylib  
> │ │ ├── libquadmath.0.dylib  
> │ │ └── libstdc++.6.dylib  
> │ ├── license.txt

Note that you will need to add a freesurfer **license.txt** for the scripts to work.

It is also possible to find a permissions problem on Mac computers when trying to run freesurfer commands. If this happens, for example on my case, I had to go to the Resources → bin, or Resources → lib → gcc folder and double click on the command that I was unable to run (e.g. mri\_watershed) and then going to System Preferences → Security & Privacy and allowing the execution from there (the window will show the last blocked command). If needed you will have to repeat the operation for each of the commands that are being blocked.

Hope this helps,
