Saving NetCdf in Matlab

In atmospheric sciences, we often deal with 4 dimensional fields. NetCdf is a practical format to save such data. Here I give an example where I save temperature in function of time, pressure, latitude, longitude

Code

```%Open the file ncid = netcdf.create(['./thefile.nc'],'NC_WRITE')   %Define the dimensions dimidt = netcdf.defDim(ncid,'time',mytimesize); dimidp = netcdf.defDim(ncid,'pressure',mypressuresize); dimidlat = netcdf.defDim(ncid,'latitude',mylatitudesize); dimidlon = netcdf.defDim(ncid,'longitude',mylongitudesize);   %Define IDs for the dimension variables (pressure,time,latitude,...) time_ID=netcdf.defVar(ncid,'time','double',[dimidt]); pressure_ID=netcdf.defVar(ncid,'pressure','double',[dimidp]); latitude_ID=netcdf.defVar(ncid,'latitude','double',[dimidlat]); longitude_ID=netcdf.defVar(ncid,'longitude','double',[dimidlon]);   %Define the main variable () temperature_ID = netcdf.defVar(ncid,'temperature','double',[dimidt dimidp dimidlat dimidlon]);   %We are done defining the NetCdf netcdf.endDef(ncid);   %Then store the dimension variables in netcdf.putVar(ncid,time_ID,mytimearray); netcdf.putVar(ncid,pressure_ID,mypressurearray); netcdf.putVar(ncid,latitude_ID,mylatitudearray); netcdf.putVar(ncid,longitude_ID,mylongitudearray);   %Then store my main variable netcdf.putVar(ncid,temperature_ID,mytemperaturearray);   %We're done, close the netcdf netcdf.close(ncid)```

24 thoughts on “Saving NetCdf in Matlab”

1. Patrick Martineau Post author

Thanks Carlos,
I must have left it out when tidying the code for presentation.
Best,
Patrick

1. Matt

Dear Patrick

This is really helpful code. Thanks a whole lot for sharing it.
I have been trying to tweak it for another close-related use I have, but try as I might, I haven’t been able to…

I want to export as a netCDF file a matrix of a single daily NCAR (surface flux) 2m temperature reanalysis. The critical thing is, it needs to be for the default global extent of the reanlaysis (i.e. 192 rows, 94 cols) and to retain the specific lat and long of the T62 Gaussian grid i.e. 88.542N to 88.542S for the lat and 0 to 358.125E. This makes it a simple 2D export, with time no longer a variable, but, the important thing is retaining the ‘original’ lat and long.

Since my ‘mytemperature’ array is 94×192 I think I only need to successfully manipulate the netcdf dimensions you specify as ‘mylatutudesize’ and ‘mylongitudesize’.
Can you suggest to me what those values should be?
One thing I am snagged on is that these dimensions are required to be scalars, but the ‘real’ lat and lon dimensions are not e.g. 88.542

I was even also trying to use ncwriteschema to adopt the dimensions scheme of the original input .nc file from NCAR, but no joy.

Would it be time consuming for you to show us how please?

Matt

1. Patrick Martineau Post author

Hi Matt,
The ‘mylongitudesize’ (integer, one element) is only the number of longitude of your grid, not the actual values. In netcdf format, you have to define the dimension size first…

The longitude values are actually stored at that line: netcdf.putVar(ncid,longitude_ID,mylongitudearray) and the values can be single precision our double precision. “mylongitudearray” is your longitude vector. In netcdf format, pressure, latitude or longitude values are actually variables stored similar to temperature for example, and can be stored using same command.

Hope this helps!

2. izidor

This helped me a lot, but there is one more issue I still have. If I create in matlab n-by-m matrix (say for temperature), data=randn(n,m), and I want to save that as netCDF for n latitudes, m longitudes, 1 level (e.g. 0) and 1 time (e.g. 1234), what is then the final step? Do I do start = [0 0 0 0] , count = [n m 1 1] ? But what is then “mytemperaturearray”, clearly it is not a n-by-m matrix. Could you help?

1. Patrick Martineau Post author

Hi Izidor,
From my understanding, your problem is that you want to save data that is function of latitude and longitude only and that your pressure and time dimension are of singleton dimension.

In my example, dimensions are {time x pressure x latitude x longitude}. Therefore your matrix “mytemperaturearray” should be of size 1 x 1 x n x m. To make a matrix of size n x m into size 1 x 1 x n x m you can do [newarray]=permute(oldarray,[3 4 1 2]). This usually works well for me.

Is your goal to save data in a loop level-by-level or day-by-day? You would have to use more advanced options of netcdf.putVar in that case. In this simple example, data is saved in one single step.

3. Alex

Thanks a lot for the code example, it’s really helpful.

On line 8, you have:
dimidlon = netcdf.defDim(ncid,’latitude’,mylongitudesize);

I think it should be
dimidlon = netcdf.defDim(ncid,’longitude’,mylongitudesize);

4. RK

Dear Patrick,

I can do writing for unlimited array.

=========
dimidt = netcdf.defDim(ncid,’time’,netcdf.getConstant(‘NC_UNLIMITED’));
.
.
.
time_ID=netcdf.defVar(ncid,’time’,’short’,[dimidt]);
netcdf.putVar(ncid,time_ID,0,mytimearray,int16([0:mytimearray]));
=======

Thanks any ways for your posting ğŸ™‚

Cheers,
-r/K-

5. Carlos

Hi PAtrick!

Patrick, I’m user new in Matlab and I’m needing save my data in netcdf format.

I did test using your script with my data, but not give right because I not know as create the variables necessary to last part from your script.

%Then store the dimension variables in
netcdf.putVar(ncid,time_ID,mytimearray);
netcdf.putVar(ncid,pressure_ID,mypressurearray);
netcdf.putVar(ncid,latitude_ID,mylatitudearray);
netcdf.putVar(ncid,longitude_ID,mylongitudearray);

How could I create the variables mytimearray, mylatitudearray and mylongitudearray?
I have variables to time, longitude and latitude, but that not are array…

Would you have an script more complete (with all steps from data entry to the rescue of the variables in netcdf) for I understand better!!

Thanks

Cheers!@
Carlos

1. Patrick Martineau Post author

Hi Carlos,
The dimension variables like pressure time latitude and longitude can be 1-D arrays (vectors)
The mytemperaturearray however needs to be a multidimensional array. In this case it needs
to be a 4-D array. Unfortunately I do not have a fully working example to share at this time. You
might want to refer to the Matlab documentation if you have any issue, there may be useful
examples on their website.

6. Carlos

Hi Dear Martineau

Martineau, I recently made a script to save the data in netcdf grads and it worked. I did the first tests to see if my variable was within the netcdf using ncview and everything went well.

However when trying to open this data in Grads, an error occurred. The file opens with all dimensions but not the data.
Do you know if there is any statement that the netcdf generated in matlab can be opened in grads?

Cheers!

Carlos

1. Patrick Martineau Post author

Hi Carlos,
I do not have enough experience with Grads to be of any help to you. Sorry!

7. Magdalena

Hello Patrick,

Thank you for the scritp, it was very helpful!

I’m having problems saving a netcdf file with a nonlinear grid (it has a meshed lat- lon) and I need to save those variables as a matrix. So the size of lat and lon is 130×143 and the size of my variable is 130x143x14000

do you know how can I adapt your script as to save the variables that way?

Thank you, Magdalena

1. Patrick Martineau Post author

Hi Magdalena,
Please let me know if I this makes any sense! From my knowledge, netCdf is working fine for rectangular grids. Because you have a non-regular grid you have a latitude matrix of 130×143 and a longitude matrix of 130×143 which can’t be stored with the method I’m using here. I would simply create two dummy dimensions x (length of 130) and y (length of 143) and then store latitude, and longitude as variables depending on x and y [lon(x,y) lat(x,y)]. Then your data can be saved as [variable(x,y,time)]. Here x and y would not have any physical meaning but would only describe the dimension of your matrix…

8. Mariano

Hello Patrick,

Thank you for this script! I’m having trouble when opening the netcdf I’ve saved with this script with ncview or GrADS. Could you help me with this? I’ll try to explain why:

So I have my variable, OLR, 4 dimensions (time x pressure x lat x lon), pressure a singleton dimension that I added so as to match this script. I pretty much follow everything, and I get the netcdf file at the end. However, when I use ncdump -h on the .nc, I get:

double time(time) ;
double pressure(pressure);
double latitude(latitude) ;
double longitude(longitude) ;
double aolr(longitude, latitude, pressure, time) ;

I think I might be having a problem in the order of the dimensions in my matlab array (as said above, (time x pressure x lat x lon)) and in the netcdf file (double aolr(longitude, latitude, pressure, time) ) and this might be causing the error, as when I open the .nc file with ncview, it shows that I have as many times as longitudes I really have (Say, if originally the dimensions are in matlab 10800 x 1 x 66 x 384, ncview understands that I have 384 times, when those were longitudes).

GrADS is also unable to open the .nc file because some dimension problem.

Hope I’m being clear and that you can help me,
Thank you!
Mariano

9. Magdalena

Hello Patrick, I forgot to answer you. Yes it worked, thank you! I leave an example for a variable “PAV” for anyone who has the same problem.

x=ones(size(lon,1),1);
y=ones(size(lon,2),1);

f_out=[ path_out ‘file.nc’ ];
ncid = netcdf.create(f_out,’NC_WRITE’);
% Crear dimensiones
dimid_lon = netcdf.defDim(ncid,’longitude’,size(x,1));
dimid_lat = netcdf.defDim(ncid,’latitude’,size(y,1));
dimid_time = netcdf.defDim(ncid,’time’,size(time,1));
% Crear variables y atributos
varid_lon = netcdf.defVar(ncid,’longitude’,’double’,[dimid_lon,dimid_lat]);
netcdf.putAtt(ncid,varid_lon,’long_name’,’Longitude’)
netcdf.putAtt(ncid,varid_lon,’units’,’degrees_east’)
%
varid_lat = netcdf.defVar(ncid,’latitude’,’double’,[dimid_lon,dimid_lat]);
netcdf.putAtt(ncid,varid_lat,’long_name’,’Latitude’)
netcdf.putAtt(ncid,varid_lat,’units’,’degrees_north’)
%
varid_time = netcdf.defVar(ncid,’time’,’double’,dimid_time);
netcdf.putAtt(ncid,varid_time,’long_name’,’Time’)
netcdf.putAtt(ncid,varid_time,’units’,’6H since 2008-01-01′)
%
varid_PAV = netcdf.defVar(ncid,’PAV_95′,’double’,[dimid_lon,dimid_lat,dimid_time]);
netcdf.putAtt(ncid,varid_PAV,’long_name’,’Variable’)
netcdf.putAtt(ncid,varid_PAV,’units’,’mm/day’)
netcdf.endDef(ncid)
%%% Agregar datos de coordenadas %%%%%%%%%%%%%%%%%%%%%%%%%%%
netcdf.putVar(ncid,varid_lon,[0 0],[size(x,1) size(y,1)],lon(:,:));
netcdf.putVar(ncid,varid_lat,[0 0],[size(x,1) size(y,1)],lat(:,:));
netcdf.putVar(ncid,varid_time,time);

%%%%%% agregando variable principal%%%%%%%%%%%%%%%%%%%%%%%%
for tt=1:size(time,1)
netcdf.putvar(ncid,varid_PAV,[0 0 tt-1],[size(x,1) size(y,1) 1],PAV(:,:,tt))
end
netcdf.close(ncid)
end

10. faiz fajary

Hello
my name is faiz

I have made myfile.nc using above script, but when I opened it in Grads, the values is odd
have any idea which part I did mistake?

regards,
-faiz-

11. Md Shamim Shams

Hi Patrick,

First of all many thanks to post such an useful code. My problem is almost similar. I am working with NOAA file named hgt.mon.mean.nc where it is arranged as [lon,lat,level,time] or 144x73x17x804 way in monthly mean.

I like to capture data HGT data from mentioned file as monthly mean from specified longitude and latitude like
east = 290;
west = 30;
north = 50;
south = -60

for specific period of time 1971 to 2011.

And finally saved data in ascii or excel format. Do you have any specific code for this in Matlab? If you then it will be really helpfull.

Best regards.

1. Patrick Martineau Post author

Hi! I’m sorry, I have never worked with this type of file.

This site uses Akismet to reduce spam. Learn how your comment data is processed.