Thursday, January 13, 2011

Max, Min and other small stuff

Just a few more tips and tricks how to improve every day code parts:
In case you are looking for the absolute maximum of a matrix, you could write:

abs_max = max(max(x));

or the more faster way:

abs_max = max(x(:));

Obviously the same is true for the minimum: min and any other function that usually runs along the first non singleton dimension of a matrix respectively.
This helps in many cases, especially when combined with direct indexing. Just for instance if you want to determine the number of NaN within a matrix. You could do:


gef = find(isnan(x(:)));
num_nan = length(gef);


gives you the number of NaNs. But this is slow and unnecessary, same can be done with a sum of a logical vector:

num_nan = sum(isnan(x(:)));


this further would work with any relation, like finding all elements larger than pi:


num_lg_pi = sum(x(:)>pi);


Another import issue to improve speed of your m-files is direct indexing and comparison optimization. Let's assume we have a matrix Depth(m,n) with depth values of an area and corresponding Lat(m,n) and Lon(m,n) matrices with the positions of each Depth value.


We are looking for the continental shelf break data, thus want to know the grid points that are shallower than 2000m and deeper than 500m.
One method would be:


[gefm gefn] = find(Depth<2000 & Depth>500);


or


gef = find(Depth<2000 & Depth>500);

and then use the found indices in the matrices Lat and Lon. But since simple addition and subtraction are faster than comparisons a faster way would be:


gef = abs(Depth-1250)<750;


and use the resulting logical matrix gef in Lat and Lon, or even use it direct if you plan not to use the results several times:


Lat(abs(Depth-1250)<750)

and

Lon(abs(Depth-1250)<750)

this method is applicable whenever you are looking for data in between two values. 
Now as a last part let's assume you have a large m-file and want to find 'data in the middle' regularly as for the depth above, looking for Data that is larger or equal min_val and smaller or equal max_val. Unfortunately Matlab has no function like:
min_val <= Data <= max_val  
but one easy way of doing that would be to define following function in you m-file header:

inbetween = @(min_val,Data,max_val)  abs(Data-(max_val+min_val)/2) < (max_val-min_val)/2 ;

then within your code you only have to do:

Lat(inbetween(500,Depth,2000))

to access all the desired Lat data that has depth between 500 and 2000. Hope that helps to make the code slimmer and easier to read!
The fastest way probably would be to copy the internal function part:

 abs(Data-(max_val+min_val)/2) < (max_val-min_val)/2

directly into the Lat(...) 

No comments:

Post a Comment