Re-sizing matrixes extracted from NetCFD files

Hi all,
I am facing a problem to which I can't seem to find a fitting answer in the already posted Q&A.
I have extracted data (temperature and population) from NetCFD files coming from several global models and global climate models (i.e. different resolutions) and find myself with several 2D matrixes (lat*lon).
Here is my problem:
I need to resize the matrixes coming from higher resolution models to fit the size of the ones with lower resolution.
Yet there's a twist:
  • I need to go from a 320*180 population matrix (data_pop) to a 192*145 one (data_pop_new): I therefore need to reduce the size without loosing any data (the lower resolution matrix needs to display more or less the same total population).
  • I need to go from a 320*160 temperature matrix (data_tas) to a 192*145 one (data_tas_new): I therefore need to reduce the size and to average the data instead of adding it (as temperature data don't add themselves).
The problem is therefore twofold : (i) how to resize a matrix to an odd size which isn't a perfect multiple of the original size, and (ii) how to do it either by averaging the data, or by adding the data.
A sample code of the manipulation to do would be truly helpful.
Thank you in advance.

 Risposta accettata

Scott MacKenzie
Scott MacKenzie il 26 Giu 2021
Modificato: Scott MacKenzie il 26 Giu 2021
I think you can leverage the image stretching function imresize to your application. The destination matrix can be any size and the new data are faithful to the original data:
M1 = peaks;
M2 = imresize(M1, [33 77])
tiledlayout(2,1)
nexttile;
surf(M1)
nexttile;
surf(M2);

6 Commenti

Hi Scott, thank you for the sharp and fast answer.
I tried your method, and it leads somewhere:
I am able to resize the data (data_1) of a smaller resolution matrix (192*145) to a higher resolution one (320*180), which I am now calling (data_1_newsize).
The original latitude and longitude of data_1 were stored the following way:
%HadGEM coordinates gathering=read any netcfd file
lat_a=ncread('tas_day_HadGEM2-ES_rcp26_r1i1p1_20651201-20751130.nc','lat_bnds');
lon_a=ncread('tas_day_HadGEM2-ES_rcp26_r1i1p1_20651201-20751130.nc','lon_bnds');
% keep only unique lat/lon values
lat_i=[lat_a(1,:) lat_a(2,end)];
lon_i=[lon_a(1,:) lon_a(2,end)];
% get the lat/lon values of each corner of the grid (required for plotting)
[lon_ii,lat_ii]=ndgrid(lon_i,lat_i);
And to plot data_1 on its original resolution, the following was made:
dd_plot=nan(size(lon_ii));
dd_plot(1:end-1,1:end-1)=data_1;
It gave a map that looked like this:
The latitude and longitude of the higher resolution netCFD file on which i would like to index data_1 was stored this way:
lat_pop=ncread('gpw_v4_population_count_rev11_1_deg.nc','latitude');
lon_pop=ncread('gpw_v4_population_count_rev11_1_deg.nc','longitude');
% keep only unique lat/lon values
lat_i2=[lat_pop+0.5;lat_pop(end)-0.5];
lon_i2=[lon_pop-0.5;lon_pop(end)+0.5];
% get the lat/lon values of each corner of the grid (required for plotting)
[lon_ii2,lat_ii2]=ndgrid(lon_i2,lat_i2);
The problem is therefore the following:
When I try to plot (data_1_newsize) and to index it to the latitude and longitude of the higher resolution netCFD file, I do the following (which must be wrong):
dd_plot2=nan(size(lon_ii2));
dd_plot2(1:end-1,1:end-1)=data_1_newsize;
Which gives the following:
Most probably because the latitude and longitude of the higher resolution netCFD don't have the same corner coordinate.
Is there a way that I could plot (data_1_newsize) over a map using the latitude and longitude of the higher resolution netCFD indexed to match exactly the original longitude and latitude?
Thank you kindly in advance for your help, which has already been really useful.
Kind regards
Tim
And I forgot:
The figure plot code of the new (and wrong) figure is the following:
figure; % open a new figure window
h=worldmap('World');
surfm(lat_ii2,lon_ii2,dd_plot2) % plot the data from the .nc file
The goal, obviously, isn't technically to plot the data, but to make sure it's indexed on the right position, so that it can be used and compared to other matrixes.
@TIMOTHEE DE TOLDI I've read your responses a few times, but, unfortunately, I'm coming up blank. I don't have any experience working with netCFD files. Sorry.
@Scott MacKenzie, Thanks a lot Scott! It's alright: from the direction you pointed, I figured how to finalize it:
Once you have prepped it as you indicated:
data_1_newsize=imresize(data_1, [360 180],'bicubic');
you indeed need to create a matrix the size of the higher resolution NetCFD file:
% create a variable the same size as 'lon_ii' and put the data we want to plot into it
dd_plot2=nan(size(lon_ii2));
dd_plot2(1:end-1,1:end-1)=data_1_newsize;
But when you plot it, the data needs to be indexed over the old coordinates:
surfm(lat_ii,lon_ii,dd_plot2)
This way it all works thanks to imresize, yet with one limit, which is the following:
As imresize averages matrix entries to resize the matrix to a new size (in a linear / bilinear / bicubic etc... manner), you can only resize matrixes containing data that can be averaged (temperature / humidity / any climate variable) but you cannot resize matrixes containing data that adds itself (population etc...). You therefore need to resize all the matrixes that can be averaged to fit the size of the one that cannot, if you wish to compare data. But that's okay in my case, as I am only working with 1 non-averageable matrix.
Thanks for everything @Scott MacKenzie!
@TIMOTHEE DE TOLDI You're welcome. And here's a quick demo using imresize of @Walter Roberson's instructions:
M1 = [1 2 3; 6 5 4; 1 5 9; 5 5 5]
sum1 = sum(sum(M1))
M2 = imresize(M1,1.5)
sum2 = sum(sum(M2))
M3 = M2 * sum1/sum2
sum3 = sum(sum(M3))
M1 =
1 2 3
6 5 4
1 5 9
5 5 5
sum1 =
51
M2 =
0.57369 1.151 1.9947 2.8066 3.0729
3.8342 3.6758 3.4443 3.2215 3.1484
5.6737 5.4366 5.0903 4.7569 4.6476
1.1778 3.0061 5.6775 8.2488 9.092
2.5269 3.6992 5.4122 7.0609 7.6016
5.2971 5.1562 4.9505 4.7524 4.6875
sum2 =
130.87
M3 =
0.22356 0.44854 0.77729 1.0937 1.1975
1.4941 1.4324 1.3422 1.2554 1.2269
2.2109 2.1186 1.9836 1.8537 1.8111
0.45897 1.1714 2.2125 3.2144 3.543
0.9847 1.4415 2.109 2.7515 2.9622
2.0642 2.0093 1.9291 1.852 1.8266
sum3 =
51

Accedi per commentare.

Più risposte (1)

To resize a matrix while keeping the totals the same, resize the matrix first, calculate the total of the resized, and then multiply the resized matrix by old_total/new_total

Categorie

Scopri di più su Climate Science and Analysis in Centro assistenza e File Exchange

Prodotti

Release

R2020b

Community Treasure Hunt

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

Start Hunting!

Translated by