Improve efficiency of for and if loops

1 view (last 30 days)
Murad Rizvanov
Murad Rizvanov on 22 Jul 2022
Edited: Murad Rizvanov on 25 Jul 2022
I have several datasets:
  1. Structure array with 45 doubles, each representing 45 years from 1978 to 2022, containing sea ice concentration data on a 304 x 448 grid for almost every day. So the size of each of 45 doubles in a structure is 304:448:365 (sic structure array)
  2. X and Y coordinates in meters for each of 304 x 448 grid cells (x_nsidc and y_nsidc) doubles
  3. Sea bed data (bathymetry) on 407 x 407 grid for continental shelf, slope, ridges abd abyss (x_shelf and y_shelf, x_slope and y_slope etc coordinates in meters)
I need to match x_nsidc and y_nsidc coordinates to x_shelf and y_shelf, x_slope and y_slope etc for each of the doubles from sic structure with 10 000 m tolerance and extract the cells with sea-ice concetration data for slope, shelf etc.
Below is the primitive code I wrote using for and if loops which seems to do the job but is too computationally demanding and inefficient. Any tips to optimize this code and make it more efficient, perhaps using find or exist commands?
Many thanks in advance.
%% Get the names of each field in sic structure
yyyy = fieldnames(sic);
[nrows, ncols] = size(yyyy);
%% Start the for loops for each of the doubles in strucure
for f = 1:nrows
sic_y = sic.(yyyy{f});
[m, n, o] = size(sic_y);
for g = 1:o
sic_shelf_y = zeros(m,n); % pre-allocate the arrays
sic_slope_y = zeros(m,n);
sic_ridge_y = zeros(m,n);
sic_abyss_y = zeros(m,n);
sic_shelf = zeros(m,n,o);
sic_slope = zeros(m,n,o);
sic_ridge = zeros(m,n,o);
sic_abyss = zeros(m,n,o);
for i = 1:m
for j = 1:n
for k = 1:length(z_slope)
for l = 1:length(z_slope)
test1 = abs(x_nsidc(i,j) - x_shelf(k,l)); % compare x-coordinates
test2 = abs(y_nsidc(i,j) - y_shelf(k,l)); % compare y-coordinates
if test1 < 1e4 && test2 < 1e4 % set thetolerance
sic_shelf_y(i,j) = sic_y(i,j); % assign the seaice concentration to the cell
else
sic_shelf_y(i,j) = sic_shelf_y(i,j); % keep the previous value
end
test1 = abs(x_nsidc(i,j) - x_slope(k,l));
test2 = abs(y_nsidc(i,j) - y_slope(k,l));
if test1 < 1e4 && test2 < 1e4
sic_slope_y(i,j) = sic_y(i,j);
else
sic_slope_y(i,j) = sic_slope_y(i,j);
end
test1 = abs(x_nsidc(i,j) - x_ridges(k,l));
test2 = abs(y_nsidc(i,j) - y_ridges(k,l));
if test1 < 1e4 && test2 < 1e4
sic_ridge_y(i,j) = sic_y(i,j);
else
sic_ridge_y(i,j) = sic_ridge_y(i,j);
end
test1 = abs(x_nsidc(i,j) - x_abyss(k,l));
test2 = abs(y_nsidc(i,j) - y_abyss(k,l));
if test1 < 1e4 && test2 < 1e4
sic_abyss_y(i,j) = sic_y(i,j);
else
sic_abyss_y(i,j) = sic_abyss_y(i,j);
end
end
end
end
end
sic_shelf(:,:,g) = sic_shelf_y;
sic_slope(:,:,g) = sic_slope_y;
sic_ridge(:,:,g) = sic_ridge_y;
sic_abyss(:,:,g) = sic_abyss_y;
end
sic_shelf(x_nsidc<0) = 0;
sic_shelf.(yyyy) = sic_shelf_y;
sic_slope(x_nsidc<0) = 0;
sic_slope.(yyyy) = sic_slope_y;
sic_ridge.(yyyy) = sic_ridge_y;
sic_abyss.(yyyy) = sic_abyss_y;
end

Answers (1)

Steven Lord
Steven Lord on 22 Jul 2022
I'm not 100% certain but based on the description I think either ismembertol or histcounts2 (specifically the 4th and 5th outputs) may be of use to you.
  1 Comment
Murad Rizvanov
Murad Rizvanov on 25 Jul 2022
Edited: Murad Rizvanov on 25 Jul 2022
Thank you. I’ve tried these options but I’m afraid neither would work. I was pretty sure it’s my lack of skill that stops me from figuring out better way. Now I wonder whether supercomputing is the only way to go.

Sign in to comment.

Products


Release

R2022a

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!