# Using Lentil with MATLAB¶

## MATLAB Lentil Interface¶

Calling Python libraries from MATLAB is as simple as configuring MATLAB to use the
appropriate Python implementation and prepending the Python command with `py.`

. Before
using Lentil in MATLAB, be sure that you you have
configured MATLAB to use the correct version of Python installed on your system

### Working with NumPy Arrays in MATLAB¶

Many Lentil methods return NumPy arrays. Unfortunately, MATLAB does not fully understand this datatype. The two MATLAB functions provided below can be used to easily convert back and forth between NumPy arrays and MATLAB matrices:

It’s also possible to read and write .npy files in MATLAB with npy-matlab

### Interacting directly with Lentil from MATLAB¶

It is possible to interact directly with Lentil within MATLAB. For example, we can
create a simple `circle()`

mask with:

```
>> mask = py.lentil.util.circle([int16(256),int16(256)],int16(128));
```

Note that MATLAB automatically does type conversion when MATLAB data is passed to Python but because MATLAB’s default numeric type is double-precision floating point, we need to explicitly convert the `shape`

and `radius`

parameters to ints before passing them to Python.

This approach is fine for debugging and some light usage, but more robust and user-friendly solutions require developing a MATLAB interface.

### Developing a MATLAB interface to a Lentil model¶

The easiest way to provide a MATLAB interface to an underlying Lentil model is to develop a separate MATLAB class that mimics the interface of a Lentil class and handles any data formatting issues that arise between MATLAB and Python. In this way, the model logic all resides within the Python code, and the MATLAB code is only responsible for managing the interface between languages. An example following this approach is available here.

When deploying a MATLAB interface to a Lentil model, it may be convenient to duplicate
the `mat2ndarray.m`

and `ndarray2mat.m`

scripts in the project’s local `matlab`

directory alongside the `.m`

interfaces. This simplifies the end user experience
because it does not require any additional path modification or management to use the
model.

For an example, see: Simple MATLAB Interface Class.

Finally, a few links that may be helpful when developing a MATLAB interface:

Warning

It is not fully understood what happens when you wrap a call to a Python object in a
`parfor`

loop in MATLAB. Buyer beware.

## Configuring MATLAB to use the correct version of Python¶

MATLAB automatically selects and loads a Python version when you type a Python command. It commonly defaults to using Python 2.7, which is not at all what we want. We need to tell MATLAB where to find the correct version of Python (>=3.7). For MATLAB r2020a or later:

```
pyenv('Version', '/path/to/python3/executable')
```

For MATLAB r2019b or earlier:

```
pyversion '/path/to/python3/executable'
```

The Python version can be set temporarily by executing the above command when MATLAB
launches or automatically by adding the command to your `startup.m`

file.

Note

If you’re using virtual environments to manage different Lentil models, the
`pyenv/pyversion`

configuration specified above won’t work. Instead, you’ll need
to call `pyenv/pyversion`

with the correct virtual environment version before
working with a model. Don’t forget to call the MKL conflict fix as well. This is
annoying. Sorry about that. It’s a MATLAB “feature”.

Warning

Once you’ve set `pyenv/pyversion`

within a MATLAB session, the only way to change
it is to restart MATLAB. This means that if you’re working with virtual
environments to manage different models, you’ll have to restart MATLAB each time you
want to switch models. This is annoying. Sorry about that. It’s a MATLAB “feature”.

For more help on setting MATLAB’s Python version, see System and Configuration Requirements.

### Resolving MKL Conflicts¶

MATLAB doesn’t always load the correct libraries the underlying Python code relies on. In particular, there seems to be some confusion about when to load MKL. There is no telltale sign this has occurred. Sometimes MATLAB crashes while other times Python method calls will error out with messages that may or may not be useful. The following command will clear up MATLAB’s confusion by handing control of which libraries Python needs back to Python:

```
py.sys.setdlopenflags(int32(10));
```

This command sets the `RTLD_NOW`

and `RTLD_DEEPBIND`

flags when the active Python
instance calls `dlopen()`

[1] [2] [3]. Note that this command is Unix only
and must be called before the Python interpreter is loaded within MATLAB but after
`pyenv/pyversion`

is set, making it a prime candidate for inclusion in `startup.m`

.

## Troubleshooting¶

### Debugging MATLAB’s Undefined variable “py” or function “py.command” error¶

Make sure Python is loaded and working:

```
>> py.print('test')
test
```

Make sure Lentil is loaded and working:

```
>> mask = py.lentil.util.circle([int16(256),int16(256)],int16(128));
```

3. Verify there are no import errors in the Python code by importing Lentil and any custom models in a Python interpreter:

```
>>> import lentil
>>> import <<your-model>>
```

For more hints, see the MATLAB documentation on Undefined variable “py” or function “py.command”

### Resolving “Python Error: ImportError: Importing the numpy c-extensions failed.” error¶

On Windows, if the system path is not correctly configured, Python will throw a lengthy error message when trying to import Numpy:

```
>> py.importlib.import_module('numpy')
Error using __init__><module> (line 54)
Python Error: ImportError:
IMPORTANT: PLEASE READ THIS FOR ADVICE ON HOW TO SOLVE THIS ISSUE!
Importing the numpy c-extensions failed. - Try uninstalling and reinstalling numpy.
...
```

There appear to be several causes, but the error is most likely triggered because Python is not able to locate the necessary Numpy DLL files. The most common culprit is not electing to add Anaconda to the Windows PATH (which for some reason is the recommended choice during installation). The issue is fixed by appending the system path. Note that it is safest to do this from within MATLAB, in case a different version of Python is on the system path and is being used by other applications.

```
setenv('path',['C:\Path\To\Anaconda3\Library\bin;', getenv('path')]);
```