Friday, March 25, 2011

A little cell magic in Matlab

Imagine we have four variables: x, y, std, and stdErr. Each variable is an array. So, we have a series of x-values, y-values, and, because each y-value is really an average of a set of values, we also have standard deviation and standard error assigned to each x.

These variables are part of a structure, called curve. So, we have our fields:
curve.x
curve.y
curve.std
curve.stdErr
Now, for whatever reason, I have pre-allocated 100 values (empty) to all my variables. Some of them are empty; some are filled. I want to get rid of the empty values. I know that I have N non-empty values. So, then:
newCurve.x = curve.x (1:N, 1);
% newCurve.x gets assigned values from 1st to Nth from curve.x along
% the 1st column

newCurve.y = curve.y (1:N, 1);
newCurve.std = curve.std (1:N, 1);
newCurve.stdErr = curve.stdErr (1:N, 1);
That does the job, doesn’t it? Well, surely so, but... it’s a bit boring. Unimaginative. Repetitive. Imagine I had fifty fields in my curve structure. I don’t want to copy-paste the same line fifty times, making corrections for a new variable each time. So, can we make this process a bit streamlined?

Well, my idea is to convert the structure into a cell; convert a cell into a matrix; use Matlab’s simple matrix operation (seen above for the matrix with size 1) to select the non-empty in the matrix; convert the matrix back into a cell, and convert the cell back into a structure. So, I have really only three steps — except that I have to tell the cell2struct function what the resulting structure’s headings are, so I have to have another line of code with those (Update: using fieldnames function, I can skip that step).


Thus:
    %% a little cell magic

    %converting to a matrix
    curve_mat = cell2mat( struct2cell(curve)' );

    %assigining non-zero values to a cell from the matrix
    shortCurve_cell = num2cell( curve_mat(1:N,:), 1);

    %converting back to a structure with field names = those of curve
    newCurve = cell2struct (shortCurve_cell, fieldnames(curve), 1);

With only four fields, I don’t really save much space (just one line of code), but you would with fifty... But that’s not the point. The point is that a soul of a former C-programmer sings when it looks at the second piece of code.

The next step is to automate the process further by writing a function outputCurve = removezeros (inputCurve, numFilled) that will take a curve structure and the number of filled values and return a structure with zero values removed. The above code will be in the function.

If you know of an even more elegant way of doing this (I am new to Matlab, so I don’t really know cell manipulation well), please comment.

By the way, in the end, if we plot the newCurve using errorBar function, we get the following:


2 comments:

mor said...

sorry, I dont know a more elegant way of doing this. The line where you talk about your soul singing made it all worth it.

Certified Ashkenazi said...

coloring the comments green made it all worth if for me.