Running Python remotely from Matlab

The goal

We want to integrate Python files and code into our Matlab workflow.

Questions to David Rotermund

Check if you are ready

Versions of Python Compatible with MATLAB Products by Release

You need to ask yourself or better Matlab if it is using the correct Python. You can check this via:

>> pyenv

ans = 

  PythonEnvironment with properties:

          Version: "3.11"
       Executable: "/data_1/davrot/P3.11/bin/python3"
          Library: "libpython3.11.so.1.0"
             Home: "/data_1/davrot/P3.11"
           Status: NotLoaded
    ExecutionMode: InProcess

If this is wrong (which it isn’t in my case) then you can change it (temporarily?) with

>> pyenv('Version','/data_1/davrot/P3.11/bin/python3')

ans = 

  PythonEnvironment with properties:

          Version: "3.11"
       Executable: "/data_1/davrot/P3.11/bin/python3"
          Library: "libpython3.11.so.1.0"
             Home: "/data_1/davrot/P3.11"
           Status: NotLoaded
    ExecutionMode: InProcess

Obviously you need to use your location for your Python installation.

Python help

>> py.help('int')
Help on class int in module builtins:

class int(object)
 |  int([x]) -> integer
 |  int(x, base=10) -> integer
[...]

Tuple and random number example

We can crate a python tuple like this:

>> py_dim = py.tuple({py.int(10), py.int(100)})

py_dim = 

  Python tuple with values:

    (10, 100)

    Use string, double or cell function to convert to a MATLAB array.

Now we can use numpy to generate random numbers:

>> py_dim = py.tuple({py.int(10), py.int(100)})
>> rng = py.numpy.random.default_rng();
>> a = rng.random(py_dim);
>> py.print(py.type(a))
<class 'numpy.ndarray'>
>> py.print(a.shape)
(10, 100)
>> py.print(a.dtype)
float64
>> whos
>> whos
  Name        Size            Bytes  Class                                   Attributes

  a           1x1                 8  py.numpy.ndarray                                  
  ans         1x1                 8  matlab.pyclient.PythonEnvironment                 
  py_dim      1x2                 8  py.tuple                                          
  rng         1x1                 8  py.numpy.random._generator.Generator    

Alternatively this is also possible:

>> b = rng.random(cell({int32(10),int32(100)}));

User defined Python modules

Our very own Python function in the file mtest_1.py:

import numpy as np

def mysquared(input:np.ndarray) -> np.ndarray:
    output = input**2
    return output

Now Matlab allows us to do this:

>> x = (1:1:10);
>> x_np = py.numpy.array(x);
>> y_np = py.mtest_1.mysquared(x_np);
>> y = double(x_np).^2;
>> sum(sum(abs(y-double(y_np))))

ans =

     0

If you change the py file, then you need to clean it from the memory via

>> clear classes

Future David here: Well, I had to do this for a file gauss_smear.py with a function gauss_smear:

if ~exist('mod', 'var')
    mod = py.importlib.import_module('gauss_smear');
end

py.importlib.reload(mod);

clearvars -except mod
mod.gauss_smear(2.0, 0.1)

Save a numpy file with Matlab

In Matlab we save data into numpy file:

>> a = rand(100,10);
>> a_np = py.numpy.array(a);
>> py.numpy.save("test_1.npy",a_np);

Now we can load it into Python:

import numpy as np

a = np.load("test_1.npy")

print(type(a)) # --> <class 'numpy.ndarray'>
print(a.shape) # --> (100, 10)
print(a.dtype) # --> float64

Loading a numpy file with Matlab

Under Python we generate a file:

import numpy as np

myrng = np.random.default_rng()

a = myrng.random((100, 10))
np.save("test_2.npy", a)

And under Matlab we load it:

>> a_np = py.numpy.load("test_2.npy");
>> a = double(a_np);
>> whos
  Name        Size            Bytes  Class               Attributes

  a         100x10             8000  double                        
  a_np        1x1                 8  py.numpy.ndarray     

References

The source code is Open Source and can be found on GitHub.