File Exchange

image thumbnail

NetCDF reader and export to ASCII

version 1.1.0.0 (2.17 KB) by Michael Pikridas
Easy to use functions that import NetCDF data to matlab and convert them to ASCII.

7 Downloads

Updated 05 May 2015

View License

This set of functions aims for those that are not necessarily familiarized with either Matlab or NetCDF handling.
The first function imports data (NetCDFreader) into matlab and the second (NetCDF2ASCII) converts these variables to ASCII.
Both functions have been tested with the WMO SDS-WAS products, however they may be used with any NetCDF fie.
How to use:
1. Assuming that all NetCDF files are located in a folder located in “C:\Users\admin\Desktop\MyNetCDF_FOLDER”, this location must be assigned as a variable (Note: Matlab commands are case sensitive).
>> fpath=' C:\Users\admin\Desktop\MyNetCDF_FOLDER ';
2. The folder where the two functions have been saved must both appear in the “Current Folder” window of Matlab.
3. >> [header] = NetCDFreader( fpath)
If the run is successful it will yield a report in the command window similar to the one found below.
-----------------------------------------------------------------------------------------------------
Files found: 2
File 1 20140907_BSC_DREAM8b_V2.nc
(1) longitude: longitude (500)
(2) latitude: latitude (250)
(3) level: level (24)
(4) time: time (25)
(5) OD550_DUST: longitude-latitude-time (500x250x25)
(6) SCONC_DUST: longitude-latitude-time (500x250x25)
(7) LOAD_DUST: longitude-latitude-time (500x250x25)
(8) EMI_DUST: longitude-latitude-time (500x250x25)
File 2 netcdf-atls03-20140915102130-63602-0557.nc
(1) longitude: longitude (320)
(2) latitude: latitude (161)
(3) time: time (14)
(4) aod550: longitude-latitude-time (320x161x14)
-----------------------------------------------------------------------------------------------------
This report indicates that two files were identified; 20140907_BSC_DREAM8b_V2.nc (file #1) and netcdf-atls03-20140915102130-63602-0557.nc (file #2).
The variables of each file are also displayed. The first file includes 8 variables and the second 4.

4. Depending on which variable the user wants to export as ASCII he may use the NetCDF2ASCII function as shown below
>> NetCDF2ASCII( header,PositionOfFile,PositionOfVariable)
Which will a create a file named NetcdfFileName_VariableName.txt
Following the example above, if someone wants to export dust load (variable # 7) located in file #1 then the command will be
>> NetCDF2ASCII( header,1,7)
This will create a file in the current directory named
“20140907_BSC_DREAM8b_V2_LOAD_DUST.txt”
The output contains the corresponding latitude, longitude, and time for each dust load. The order is dictated by the NetCDF file itself. However, the user does not need to guess since it is indicated in the report above by the numbers in the parenthesis.

Cite As

Michael Pikridas (2020). NetCDF reader and export to ASCII (https://www.mathworks.com/matlabcentral/fileexchange/48724-netcdf-reader-and-export-to-ascii), MATLAB Central File Exchange. Retrieved .

Comments and Ratings (10)

Hi John
This function holds plenty of assumptions. Assume you want to write down into ascii variable 5 which is linked with 2 dimensions bnds and lon.
Just by reading the output of NetCDFreader the bnds is not defined, which is very strange.
Also this function assumes that each dimension corresponds to a vector variable. This means that lon, lat and time are vectors. If you take a closer look your file starts with olr which is 3d matrix. This is very problematic for this code.

If you still care to send me your file to find a workaround to this problem, I will. If you put my name along with CyI on google you will find my email.

Cheers!

Hello,
I have tried the scripts to convert netcdf file to ascii. NetCDFreader is working, But it showing an error in converting ,nc file to ascii.

Error using '
Transpose on ND array is not defined. Use PERMUTE instead.

Error in NetCDF2ASCII (line 34)
header(filepos).var(count).data=(header(filepos).var(count).data)';

The result that I got after running NetCDFreader is

[header]=NetCDFreader(fpath)
Files found: 1
File 1 olr-daily_v01r02_20150101_20151231.nc
(1) olr: lon-lat-time (360x180x365)
(2) lon: lon (360)
(3) lat: lat (180)
(4) time: time (365)
(5) lon_bounds: bnds-lon (2x360)
(6) lat_bounds: bnds-lat (2x180)
(7) time_bounds: bnds-time (2x365)
header =
struct with fields:
name: 'olr-daily_v01r02_20150101_20151231.nc'
ndim: 4
nvar: 7
natt: 46
dimnames: {4×1 cell}
dimsizes: [365 180 360 2]
var: [1×7 struct]

Looking forward to hear from you
Regards

Nikole Ward

I'm working to get the NetCDFreader to work so that I can write variables to ASCII using the second function, however, I'm receiving the following error, and am unsure if this is due to change in versions of MATLAB. The error reads as follows:

Error using netcdflib
START argument cannot be empty.

Error in netcdf.getVar (line 136)
data = netcdflib(funcstr,ncid,varid,varargin{:});

Error in NetCDFreader (line 40)
header(i).var(k).data =
netcdf.getVar(ncid,k-1,zeros(length(header(i).var(k).dim),1),l); %% Retrieve
Data

Any assistance on this issue would be much appreciated.

Thank you.

Hello,
I combined the two files together "NetCDFreader + NetCDF2ASCII" and then I changed the path to the .nc files path as shown below. But the script didn't work. I also tried to make the script work on multiple netCDF files and output them automatically to ascii files. I herewith attached the script. Please, I hope if you can help me and explain to me more in this regard. Thanks

function [header] = NetCDFreader( G:\GoogleDrive_MST_5-15-2017\Weather_Data_Analysis\TRMM 6-4-2017\Matlab\test)
% NetCDFreader reads NetCDF data and converts to ASCII
%
% [header] = NetCDFreader( fpath)
% where
% fpath is the filepath where the NetCDF files are located.
% Note: Only .nc files will be read.
%
% header is a structure containing all the information of the NetCDF file
%
% This function has been tested against SDS-WAS NetCDF data.
% A report is created if the function runs succesfully.
%
% Michael Pikridas 8 Sep 2014
% The Cyprus Institute for DNICast

files=dir([fpath,'\*.nc']); %reading files
if isempty(files)==1
error('Cannot find any NetCDF file')
end

for i=1:length(files)
%% Retrieve Information
ncid = netcdf.open([fpath,'/',files(i).name],'NC_NOWRITE'); %open file
header(i).name=files(i).name;
[header(i).ndim, header(i).nvar, header(i).natt, ~] = netcdf.inq(ncid); %reading dimensions
for j=1:header(i).ndim %read the name and length of each dimension
[header(i).dimnames{j,1}, header(i).dimsizes(j)] = netcdf.inqDim(ncid,j-1);
end

for k=1:header(i).nvar %read the name and length of each dvariable
[header(i).var(k).name, foo, header(i).var(k).dim, header(i).var(k).natt] = netcdf.inqVar(ncid, k-1);
header(i).var(k).xtype=assign_types(foo); % Interpreting flags into classes
l=[];
for ii=1:length(header(i).var(k).dim) % Assigning names to the dimensions
header(i).var(k).dimnames{ii,1}=header(i).dimnames{header(i).var(k).dim(ii)+1};
l=[l, header(i).dimsizes(header(i).var(k).dim(ii)+1)]; %calculate how many variables are included
end
header(i).var(k).data = netcdf.getVar(ncid,k-1,zeros(length(header(i).var(k).dim),1),l); %% Retrieve Data
end
netcdf.close(ncid)
end

%% Write Report
fprintf('Files found: %d\n',length(files))
for i=1:length(files)
fprintf('File %d %s\n',i,header(i).name)
for k=1:header(i).nvar
str1=[];
str2=[];
for ii=1:length(header(i).var(k).dim)
str1=[str1,header(i).var(k).dimnames{ii},'-'];
str2=[str2,num2str(header(i).dimsizes(header(i).var(k).dim(ii)+1)),'x'];
end
str1(end)=' ';
str2(end)=[];
fprintf(['(%d) %s: %s(%s) \n'],k,header(i).var(k).name, str1, str2)
end
fprintf('\n')
end
end % function end

function tp=assign_types(flag)
switch flag
case 1
tp='unknown';
case 2
tp='char';
case 3
tp='integer short';
case 4
tp='integer';
case 5
tp='real';
case 6
tp='double';
end
end

function NetCDF2ASCII( header,filepos,varpos )
% NetCDF2ASCII Converts NetCDF data provided by NetCDFreader to ASCII
%
% NetCDF2ASCII( header,PositionOfFile,PositionOfVariable)
% where
% header is a structure created by NetCDFreader function that contains all the information of the NetCDF file
% filepos and varpos are integer numbers that control which file and
% variable will be converted to ASCII.
%
% The output is a file named NetcdfFileName_VariableName.txt
%
%
% This function has been tested against SDS-WAS NetCDF data.
%
% Michael Pikridas 8 Sep 2014
% The Cyprus Institute for DNICast


l=length(header(filepos).var(varpos).data(:)); %how many points there are
dim=length(header(filepos).var(varpos).dim)+1; %how many dimensions it has+1
data=nan(l,dim); %preallocating
data(:,end)=header(filepos).var(varpos).data(:);
if dim==2 %if the selected variable has one dimension
data(:,1)=[]; %delete the first column
else
for ii=length(header(filepos).var(varpos).dim):-1:1
count=1;
while header(filepos).var(varpos).dim(ii)~=header(filepos).var(count).dim
count=count+1; %get at which position each variable is located. Assumes variable are at the beginning
end
foo=size(header(filepos).var(varpos).data);
foo(ii)=1;
if size(header(filepos).var(count).data,2)~=1 %making the vector a column
header(filepos).var(count).data=(header(filepos).var(count).data)';
if size(header(filepos).var(count).data,2)~=1
error('This function assumes that all dimensions of this variable correspond to vectors')
end
end
perfoo=1:length(header(filepos).var(varpos).dim); %all the dimensions involved
perfoo(ii)=1;%Because I turned it into a column
perfoo(1)=ii;%exchanging places
duplicates=repmat(permute(header(filepos).var(count).data,perfoo),foo);%duplicate variables into the size of the data
data(:,dim-ii)=duplicates(:); %puts the variables in reverse order, data are in normal order
end
end %ends if
%% Writing to ASCII
strname=[strtok(header(filepos).name,'.'),'_',header(filepos).var(varpos).name,'.txt']; %Determining filename
dlmwrite(strname,double(data),'\t') %writing
end

Please, I couldn't read or convert the netCDF files. any help, suggestion.. Thanks

Amanda Gott

This is the output of the reader, it's the sst that I need.

>> [header] = NetCDFreader(fpath)
Files found: 6
File 1 Subset_1980_1984.nc
(1) latitude: latitude (180)
(2) longitude: longitude (360)
(3) sst: longitude-latitude-time (360x180x60)
(4) time: time (60)

File 2 Subset_1980_present.nc
(1) latitude: latitude (180)
(2) longitude: longitude (360)
(3) sst: longitude-latitude-time (360x180x445)
(4) time: time (445)

File 3 Subset_1985_1989.nc
(1) latitude: latitude (180)
(2) longitude: longitude (360)
(3) sst: longitude-latitude-time (360x180x60)
(4) time: time (60)

File 4 Subset_1990_1994.nc
(1) latitude: latitude (180)
(2) longitude: longitude (360)
(3) sst: longitude-latitude-time (360x180x60)
(4) time: time (60)

File 5 Subset_1995_1999.nc
(1) latitude: latitude (180)
(2) longitude: longitude (360)
(3) sst: longitude-latitude-time (360x180x60)
(4) time: time (60)

File 6 Subset_2000_2004.nc
(1) latitude: latitude (180)
(2) longitude: longitude (360)
(3) sst: longitude-latitude-time (360x180x60)
(4) time: time (60)

header =

1×6 struct array with fields:

name
ndim
nvar
natt
dimnames
dimsizes
var

@Amanda Gott

It seems that one of your independent variables is not a vector.

Independent variables in the example above are
(1) longitude: longitude (500)
(2) latitude: latitude (250)
(3) level: level (24)
(4) time: time (25)

They all have one number following in the brackets indicating how many elements they include. I think in your case you get something like MxNxK size variable.

Since you can read it with NetCDFreader can you send me the result printed on the screen?

Kind Regards

Amanda Gott

I'm getting two seperate errors trying to convert my file.

>> NetCDF2ASCII(header,1,3)
Error using '
Transpose on ND array is not defined. Use PERMUTE instead.

Error in NetCDF2ASCII (line 34)
header(filepos).var(count).data=(header(filepos).var(count).data)';

Just updated some bug fixes I encountered myself.

[header] = NetCDFreader( myfpath)
should provide the structure under "header" not "ans".

NetCDFreader( myfpath)
should provide the answer under "ans".
However this is not your issue.

When NetCDFreader is applied it lists the files it found and its contents.

Can you provide that please for the problematic file (#2 in the example you gave).

I tried to duplicate the error without success. But I am under the impression that the this specific nc file includes besides numbers, strings or characters.

This is a simple function designed to work only with numeric data.

Hope it helps

Thanks for scripts. I was able to read .nc files in current folder. However, I was unable to convert variables to ASCII file. Here's what I entered in the command window, and I got the following errors:

>> NetCDF2ASCII header 2 1
Improper index matrix reference.

Error in NetCDF2ASCII (line 22)
data(:,end)=header(filepos).var(varpos).data(:);

Can you please help? Also, note, that the structure array is named "ans" after running the NetCDFreader function.

Updates

1.1.0.0

Bug fix
Can read files from provided path (before only from current folder)
Can write to ASCII a variable that has one dimension. Previously only variables with at least 2 dimension would be written.

MATLAB Release Compatibility
Created with R2013b
Compatible with any release
Platform Compatibility
Windows macOS Linux
Tags Add Tags