I have a Matlab function which accepts a 3 dimensional vector and returns a single number. I want to use this through MATLink to make a 3d plot.

A unit sphere:

 Norm[{x, y, z}, 2]^2 == 1, {x, -1, 1}, {y, -1, 1}, {z, -1, 1}]

I now want to replace the Norm with my function:

myfunc= MFunction["myfunc"];
ContourPlot3D[myfunc[{x, y, z}] == 1, {x, -1, 1}, {y, -1, 1}, {z, -1, 1}]

but I get errors:

MSet::unsupp: Unsupported data type. The expression "x" can't be converted. MFunction::args: The arguments at positions {1} to "myfunc" could not be translated to MATLAB....

I am fairly certain I'm missing something obvious but I this is my first time with MATLink.

  • $\begingroup$ The problem is that the symbolic expression {x,y,z} is passed to myfunc before the values of x,y,z are substituted in. Symbols can't be transferred no MATLAB, only numbers can. So you get an error: The expression "x" can't be converted. The solution is to use a wrapper function which will only evaluated for numerical vectors. Unfortunately I don't have time to write an answer right now, but I'll do it a few hours later (or more likely someone else will do it sooner). I just wanted to point you to the solution beforehand. $\endgroup$ – Szabolcs Jan 30 '14 at 17:04
  • $\begingroup$ That would be extremely helpful, thanks. I'll try to find information on it, in case I can do it myself as well. $\endgroup$ – asdfa Jan 30 '14 at 18:37

The problem is that the symbolic vector {x,y,z} is passed to the function before the values for x, y and z are substituted. Symbols cannot be transferred to MATLAB, so you get an error:

In[1]:= Needs["MATLink`"]

In[2]:= OpenMATLAB[]

In[3]:= norm = MFunction["norm"]
Out[3]= MFunction["norm"]

In[4]:= norm[{x, y, z}]

During evaluation of In[4]:= MSet::unsupp: Unsupported data type. The expression "x" can't be converted.

During evaluation of In[4]:= MFunction::args: The arguments at positions {1} to "norm" could not be translated to MATLAB.

Out[4]= $Failed

If you use explicit numbers, all is fine:

In[5]:= norm[{1, 2, 3}]
Out[5]= 3.74166

You can use a wrapper function to prevent Mathematica from attempting to evaluate norm[{x,y,z}]. This is a very typical situation in Mathematica and it's not specific to MATLink. See here for more information.

So let's make the wrapper function:

norm2[x_?(VectorQ[#, NumericQ] &)] := norm[x]

Now norm2 will only evaluate when supplied with numerical arguments, and we can avoid the error messages:

In[8]:= norm2[{x, y, z}]
Out[8]= norm2[{x, y, z}]

In[9]:= norm2[{3, 2, 1}]
Out[9]= 3.74166

The ContourPlot3D will work as well, with one big caveat:

 norm2[{x, y, z}] == 1, {x, -1.1, 1.1}, {y, -1.1, 1.1}, {z, -1.1, 1.1}, MaxRecursion -> 0, PlotPoints -> 5]

You need to reduce the number of evaluations it does so significantly that the quality of the output will suffer a lot. Otherwise it will take a very long time to evaluate. With the default options, ContourPlot3D would do about half a million evaluations for this plot. Unfortunately MFunction is not very fast at the moment, so you won't be able to complete more than a few hundred evaluations in a reasonable amount of time.

The reason for the bad performance is that there is a constant overhead to every call to an MFunction. This overhead is due to limitations (and bugs :-( ) of the MATLAB Engine API that MATLink uses to communicate with MATLAB. The overhead is considerably worse on Mac/Linux than on Windows, primarily because of the low quality implementation of the MATLAB Engine on these platforms.

As of 2014 January a rewrite of MATLink is in progress. The next version will use a different way to communicate with MATLAB (the MEX API) and will significantly reduce this overhead, making these types of applications much more feasible.

This performance issue is not always a problem, but ContourPlot3D being a 3D plotting function it needs to make a very large number of evaluations (many more than a 1D or a 2D one would), so the performance problem is particularly apparent here.

As a workaround you could consider generating a large number of points (Tuples[Range[-1.1, 1.1, 0.01], 3]), and sending them all at once to MATLAB for processing, then sending all the result back in one go and using ListContourPlot3D[..., Contours -> {1}] on them.

  • $\begingroup$ @Szablocs I did the same but did not post due to this timing issue. Its better to get the performance related explanation from the developer himself. I am really looking forward to the update of MATLink when the communication overhead becomes really negligible. It is already a great tool but with such an update MATLink will be a killer app. $\endgroup$ – PlatoManiac Jan 30 '14 at 20:07
  • $\begingroup$ That was very helpful, thanks! Your work helped a likely publication for tomorrow, thanks a bunch again. $\endgroup$ – asdfa Jan 30 '14 at 20:34

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.