Question

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?

Was it helpful?

Solution

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!

OTHER TIPS

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.

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

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top