arokem / python-matlab-bridge

A simple Python => MATLAB(R) interface and a matlab_magic for ipython
BSD 2-Clause "Simplified" License
332 stars 97 forks source link

Same sized numpy arrays stacking together #228

Closed alexvorndran closed 2 years ago

alexvorndran commented 8 years ago

If I execute the following example code, it will print False Not enough input arguments.. If I include the save(...) command for debugging purposes and load debug_dump.mat afterwards, it only holds a single variable called a with size 10x10x3.

Is there a flaw in my code that I am not able to spot or is this problem rooted somewhere in the pymatbridge package? I am using pymatbridge 0.6.0-dev with Python 2.7.9 and Matlab R2014a.

def test():
    dummy1 = np.random.normal(size=(10, 10))
    dummy2 = np.random.normal(size=(10, 10))
    dummy3 = np.random.normal(size=(10, 10))

    mlab = Matlab()
    mlab.start()
    returnval = mlab.run_func('multiply_them.m', dummy1, dummy2, dummy3, nargout=1)
    mlab.stop()

    print returnval['success'], returnval['content']['stdout']

if __name__ == '__main__':
    test()

The matlab function stored in multiply_them.m:

function d = multiply_them(a, b, c)
    % save('debug_dump') % store all known variables in workspace
    d = a*b*c;
end
arokem commented 8 years ago

You're right. This does seem to be a bug in pymatbridge.

On Thu, Oct 29, 2015 at 8:14 PM, Alex Vorndran notifications@github.com wrote:

If I execute the following example code, it will print False Not enough input arguments.. If I include the save(...) command for debugging purposes and load debug_dump.mat afterwards, it only holds a single variable called a with size 10x10x3.

Is there a flaw in my code that I am not able to spot or is this problem rooted somewhere in the pymatbridge package? I am using pymatbridge 0.6.0-dev with Python 2.7.9 and Matlab R2014a.

def test(): dummy1 = np.random.normal(size=(10, 10)) dummy2 = np.random.normal(size=(10, 10)) dummy3 = np.random.normal(size=(10, 10))

mlab = Matlab()
mlab.start()
returnval = mlab.run_func('multiply_them.m', dummy1, dummy2, dummy3, nargout=1)
mlab.stop()

print returnval['success'], returnval['content']['stdout']

if name == 'main': test()

The matlab function stored in multiply_them.m:

function d = multiply_them(a, b, c) % save('debug_dump') % store all known variables in workspace d = a_b_c;end

— Reply to this email directly or view it on GitHub https://github.com/arokem/python-matlab-bridge/issues/228.

isbadawi commented 8 years ago

This seems to be an issue with json_load on the matlab side. In the request we have func_args as an array of three objects representing ndarrays. json_load converts that to a cell array of three arrays, which is what we want, but then merges that into a 10x10x3 array, because by default it always tries to create matlab arrays when possible. This is controlled by the 'MergeCell' option, but we can't set that to false because the shape of the array is passed in the request too (e.g. [10,10]), and there we do want the cell array to be merged.

With the following hack the test program works. But someone should come up with a cleaner solution.

diff --git a/pymatbridge/matlab/util/json_v0.2.2/json/json_load.m b/pymatbridge/matlab/util/json_v0.2.2/json/json_load.m
index ed2660f..8687ad4 100644
--- a/pymatbridge/matlab/util/json_v0.2.2/json/json_load.m
+++ b/pymatbridge/matlab/util/json_v0.2.2/json/json_load.m
@@ -119,8 +119,13 @@ function value = parse_data_(node, options)
         warning('json:fieldNameConflict', ...
                 'Field %s renamed to %s', field, safe_field);
       end
+      oldMergeCell = options.MergeCell;
+      if strcmp(field, 'func_args')
+        options.MergeCell = false;
+      end
       value.(safe_field) = parse_data_(node.get(javaObject('java.lang.String', key)), ...
                                        options);
+      options.MergeCell = oldMergeCell;
     end
     % Check if the struct just decoded represents an array or complex number
     if isfield(value,'ndarray') && isfield(value, 'shape')