4

Suppose I have a column matrix pols containing vectors of [theta, rho, z]. Which means, if I have 9 such vectors, it will be a 9x3 matrix. It is quite handy to have them arranged as such, because I can just feed any one of them to functions like pol2cart:

cart3 = pol2cart(pols(3,:));

and for a certain vector, I can find its components via the indices 1, 2, 3:

rho5 = pols(5,2);

But sometimes the matrix is actually within another wider matrix, and could be in the middle instead of the beginning, such that the above might become:

rho5 = pols(5,6);

In order to make the code more readable in case someone else has to maintain it, is there anyway to refer to an index via a unique name? Like

rho5 = pols(5).rho;

where it could be defined earlier that .rho maps to the column which has the value of rho.

I've ventured into converting matrices to cells then to array using mat2cell and cell2struct but it doesn't seem practical. Or, I could make an array of structs, but then I lose the ability to do pol2cart(pols), and instead must do

pol2cart(pols.theta, pols.rho, pols.z);

So to repeat the question: can I map the indices to unique names?

gnovice
  • 125,304
  • 15
  • 256
  • 359
syockit
  • 5,747
  • 1
  • 24
  • 33
  • 1
    Your first line of code wouldn't work. [POL2CART](http://www.mathworks.com/help/techdoc/ref/pol2cart.html) requires 2 (or 3) input arguments, not a single vector argument. Which version of MATLAB are you using? – gnovice Apr 19 '12 at 16:05
  • Actually I only tested it on Octave, because I don't have Matlab but I have to help out my friend who's using it. So if pol2cart doesn't accept such argument, then the first argument doesn't hold. Still, it can be handy to be able to address to indices via names. – syockit Apr 20 '12 at 10:39

3 Answers3

3

For the default MATLAB data types, no, you can't really do that. You could, however, create your own new data type (i.e. class object) to store your data. Within the class definition you would overload the subsref method to define how subscripted referencing (i.e. using (), {}, or .) behaves for your new object. This could get rather tricky with regards to dealing with arrays of objects, but it is possible.

Note that you would also have to create overloaded methods for all the existing functions you want to use on your new data type. Specifically, you would have to create a pol2cart method for your object that could internally call the built-in pol2cart function with the appropriate pieces of data from your object passed as arguments.

...And this brings me to a simpler solution for your current situation. Instead of making a whole new type of class object, you could create a structure array (or scalar structure of arrays) to store your data and simply create a new overloaded pol2cart function specifically for struct data types that will simplify the calling syntax.

I discuss more details of overloading functions for built-in data types in two other answers here and here. In short, you would create a folder called @struct and place it in a folder on your MATLAB path. In this @struct folder you would then put this overloaded function:

function varargout = pol2cart(polarCoordinates)
  [varargout{1:nargout}] = pol2cart(polarCoordinates.theta, ...
                                    polarCoordinates.rho, ...
                                    polarCoordinates.z);
end

Note that this is a stream-lined version of the function, without error checks on the input, etc. Now, let's make some sample data:

pols = rand(9, 3);  %# A 2-D array of data
polStruct = struct('theta', pols(:, 1), ...  %# Convert it to a scalar
                   'rho', pols(:, 2), ...    %#   structure of arrays
                   'z', pols(:, 3));

And you could access the rho value of the fifth row as follows:

rho5 = pols(5,2);
rho5 = polStruct.rho(5);

If you wanted to convert from polar to cartesian coordinates, here's how you would do it for each data type:

[X,Y,Z] = pol2cart(pols(:,1), pols(:,2), pols(:,3));  %# Calls the built-in one
[X2,Y2,Z2] = pol2cart(polStruct);  %# Calls the overloaded one

And you can check that they each give identical results as follows:

>> isequal([X Y Z],[X2 Y2 Z2])

ans =

     1   %# True!
Community
  • 1
  • 1
gnovice
  • 125,304
  • 15
  • 256
  • 359
  • Thanks for the detailed answer! I suppose classes is the way to go… though I'm afraid I can't employ it in the code for fear of spooking the owner of the code, who's not familiar with programming and OO paradigm. – syockit Apr 20 '12 at 10:43
1

OK, the formal answer is probably "no" as given by woodchips above. However, if you really want to do something like that, you might be able to use a semi-hack. Specifically, you can define a class and overload an operator to achieve (almost) what you want. Unfortunately, I see that Matlab doesn't allow overloading ., so you have to use some other operator. (see edit below)

Just to give you the idea, here is a class that returns the i-th row of a matrix M by M^i.

classdef Test
  properties
    M;
  end

  methods
    function this = Test(M)
      this.M = M;
    end

    function res = mpower(this, i)
      res = this.M(i, :);
    end
  end
end

And it can be run like this:

>> tmp = Test([1 2; 3 4]);
>> tmp^1

ans =

     1     2

>> tmp^2

ans =

     3     4

Use at your own risk! :)

Edit:

I was wrong above. As mentioned in gnovice's answer you can actually define the . operator for a custom class using method subsref.

3lectrologos
  • 9,469
  • 4
  • 39
  • 46
  • Wow that's sicko! Great to know that I can do that :) Though maybe not suitable for when working with other people (I think this is the reason why some people shun operator overloading?) – syockit Apr 20 '12 at 10:38
0

No. You cannot do so. As simple as that.