Closed tsdev closed 7 years ago
As the error message states, some part of your code is calling genlattice
. This seems unrelated to the code you show.
That said, for now the only way to call methods is to use the functional form, i.e. mat.cut(a)
.
The OO form shouldn't be very hard to implement, though. Maybe I'll find the time to do it in the next few weeks.
BTW, the package is really amazing and thank you for sharing it!
You are right, I changed the method names in the example.
Implementing methods would make calling Matlab scripts more Python native. I guess you could just send the result of the methods(myClass)
command from Matlab back to Python and then compare to the Python call. This would make all the standard functions on matrices also callable via methods (even C = A.plus(B)
would work then in Python if class(A) is double for example).
Then you could even overload standard python operators, such as add, etc. that would make even simpler calls between Matlab objects:
C = A + B
I guess the only problem with my above examples is that transplant automatically converts any Matlab matrix to numpy array. If there would be a way to tell transplant not to convert matlab arrays, we could call Matlab commands on arrays that don't exist in Python, e.g. accumarray using the simple call (as accumarray is also listed as a method of double):
C = A.accumarray(...)
Another related question:
My custom class has some public properties, but I didn't define a get/set method to access them. Would it be possible to add access in transplant to public properties? It should work the same way as methods, you just need the store the output of properties(myClass)
as well.
One last question:
I am using a similar package pymatbridge, that enables the direct call of any piece of Matlab code via sending a string and using eval(str) in Matlab. Is similar thing possible in transplant? I am interested because this mode combined the %matlab magic in Jupyter enables to write native Matlab scripts in Jupyter. At present I need both pymatbridge and transplant depending on the task I want to do.
I guess the more "correct" implementation would return a function handle from get_proxy
(object member access). Your problem is actually a result of a peculiarity of Matlab's get
, since get_proxy
currently gets translated as get(object, name)
, which works for properties, but fails for methods. It is easy to provide a fail-over for methods, though. Another complication is that Matlab does not provide a function for the @
operator, which means I will have to use eval
instead to generate the necessary function handle (always ugly).
The accumarray
example would already work, simply by calling mat.accumarray(numpy_array, ...)
.
Re: your related question:
Public properties can be set and read using normal Python access, i.e. obj.foo = "bar"
for a Matlab object obj
that has a property foo
.
Re: your last question:
You can simply use Matlab's eval
function: mat.eval('help disp')
works just fine. However, you might want to use mat.evalin('base', 'help disp')
instead, to avoid messing with Transplant's internal namespace (this is another problem I can't work around).
Thanks for clarifying most of my questions. Indeed you can easily access arbitrary class method/property names defined in a string using the obj.('method')
and obj.('property')
notation. I don't know what Matlab version introduced this, but it works in Matlab R2016b. I also suggest to change calling the get/set methods to the above notation as they are not always defined for user classes (unless they are derived from the matlab.mixin.SetGet
superclass).
I added a few commits that should make your use case possible. There were indeed a few bugs concerning object properties and methods. As it turns out, the previous implementation could not access properties of non-graphical objects.
The current version should allow property access, and enable method(obj)
and obj.property
. obj.method()
does not work yet, and turned out to be more difficult than anticipated. I am working on it, though.
Thank you for the quick fix! I had a look at the update. The call matlab.method(obj)
works, however the method(obj)
returns the error: NameError: name 'method' is not defined
.
Do you have an easy way of debugging transplant in Matlab? At present, even when using the -desktop
argument at startup, I cannot access the Matlab window for debugging.
As of the latest commit, obj.method()
should work as well.
Here is a more complete example I used for testing:
Consider the very simplistic class
classdef testclass
properties
foo
end
methods
function obj = testclass(x)
obj.foo = x;
end
function it = giveittome(obj)
% bar baz
it = obj.foo;
end
end
end
With this in the Matlab path, the following code works:
import transplant
m = transplant.Matlab()
x = m.testclass(42)
print(x) # shows what Matlab would show
print(m.giveittome(x)) # call using function syntax
print(m.giveittome.__doc__) # documentation still works
print(x.giveittome()) # call using method syntax
print(x.giveittome.__doc__) # documentation still works
Please do report any errors you find. I found a few of them myself, but I'm sure there are more of them lurking in the code.
With the latest version, the above code should continue to work, but the implementation was simplified tremendously by moving much of the meta programming to Python. There is a certain performance overhead for this, but it shouldn't be too bad.
Can you confirm that this fixes your problem?
It works perfectly!
I have a user defined matlab object with a method, e.g. myObj.cut(). When I try the following lines in python:
I get the following error:
What would be the right way to call the cut() method? The above script works with the official Matlab Python interface. Also would it be possible to modify transplant, that object methods could be called directly:
a.cut()
instead ofmat.cut(a)
?