function fname = nc_kickstarter(varargin)
%NC_KICKSTARTER Generates netCDF files that comply with the CF and ACDD conventions
%
% Generates netCDF files that comply with the CF and ACDD netCDF
% conventions. The function uses the netCDF kickstarter webservice to
% actually generate the netCDF file. It can use the data that is to be
% stored in the file to extract values for netCDF attributes, like the
% dimension bounds. When using data it also supports the immediate
% addition of data to the generated file.
%
% Additionally, the function also supports the generation of CDL
% templates, Python scripts, Matlab scripts and ncML files through the
% netCDF kickstarter webservice.
%
% The netCDF kickstarter webservice is further explained on the following
% Wiki page:
%
% http://publicwiki.deltares.nl/display/OET/netCDF+kickstarter
%
% Syntax:
% fname = nc_kickstarter(varargin)
%
% Input:
% varargin = host: host to webservice
% template: CDL template to use (if not provided, you can
% select it from a list)
% epsg: EPSG code for coordinate reference system (if
% not provided, you can select it from a list)
% format: Output format (cdl, netcdf, python, matlab or
% ncml; default: netcdf)
% kickstarter:Name of the netCDF file to be generated. This
% is only relevant for the generation of scripts
% (format = python or matlab)
% data: Flag to enable extraction of netCDF attributes
% from data (default: false)
%
% Output:
% fname = Path to generated file
%
% Examples:
% % generate netCDF file
% fname = nc_kickstarter()
% % generate netCDF file using data
% fname = nc_kickstarter('data',true)
% % generate CDL template using data
% fname = nc_kickstarter('format','cdl','data',true)
% % generate Matlab script using data
% fname = nc_kickstarter('format','matlab','data',true)
%
% See also nc_kickstarter_data_read, nc_kickstarter_data_add,
% nc_kickstarter_customfcn
%% Copyright notice
% --------------------------------------------------------------------
% Copyright (C) 2013 Deltares
% Bas Hoonhout
%
% bas.hoonhout@deltares.nl
%
% Rotterdamseweg 185
% 2629 HD Delft
%
% This library is free software: you can redistribute it and/or modify
% it under the terms of the GNU General Public License as published by
% the Free Software Foundation, either version 3 of the License, or
% (at your option) any later version.
%
% This library is distributed in the hope that it will be useful,
% but WITHOUT ANY WARRANTY; without even the implied warranty of
% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
% GNU General Public License for more details.
%
% You should have received a copy of the GNU General Public License
% along with this library. If not, see .
% --------------------------------------------------------------------
% This tool is part of OpenEarthTools.
% OpenEarthTools is an online collaboration to share and manage data and
% programming tools in an open source, version controlled environment.
% Sign up to recieve regular updates of this function, and to contribute
% your own tools.
%% Version
% Created: 14 Aug 2013
% Created with Matlab version: 8.1.0.604 (R2013a)
% $Id$
% $Date$
% $Author$
% $Revision$
% $HeadURL$
% $Keywords: $
%% read settings
OPT = struct( ...
'host','http://dtvirt61.deltares.nl/netcdfkickstarter', ...
'template','', ...
'epsg',0, ...
'format','netcdf', ...
'filename','kickstarter', ...
'data',false);
OPT = setproperty(OPT, varargin);
pref_group = 'netcdfKickstarter';
% determine file extension
switch lower(OPT.format)
case 'cdl'
ext = '.cdl';
case 'netcdf'
ext = '.nc';
case 'python'
ext = '.py';
case 'matlab'
ext = '.m';
case 'ncml'
ext = '.xml';
otherwise
error('Unsupported file format [%s]', OPT.format);
end
% initialize query string
query_string = '';
%% coordinate system
if isempty(OPT.epsg) || OPT.epsg <= 0
warning('off','json:fieldNameConflict');
url = [OPT.host 'json/coordinatesystems'];
crs = nc_kickstarter_optionlist(url, ...
'format','{x_name}', ...
'pref_key','epsg', ...
'prompt','Choose coordinate system number');
% extract number from result
OPT.epsg = str2double(regexprep(crs.epsg_code,'\D+',''));
end
% append to query string
query_string = sprintf('%s&epsg=%s',query_string,urlencode(sprintf('EPSG:%d',OPT.epsg)));
%% choose a template
if isempty(OPT.template)
url = [OPT.host 'json/templates'];
OPT.template = nc_kickstarter_optionlist(url, ...
'pref_key','template', ...
'prompt','Choose template number');
end
%% define variables
var = nan;
vars = {};
n = 1;
while ~isempty(var)
% ask for variable name
var = input(sprintf('Name of variable #%d (press ENTER to skip):\n',n),'s');
% quit if no variable name is specified
if isempty(var)
break;
end
% show header with variable name
fprintf('\n');
fprintf('----------------------------------------\n');
fprintf('%s\n',upper(var));
fprintf('----------------------------------------\n');
fprintf('\n');
% retrieve all properties to be specified for a variable
url = [OPT.host 'json/templates/' [OPT.template '?category=var']];
data = urlread(url);
m = json.load(data);
[m.value] = deal('');
% loop over properties
for j = 1:length(m)
% check if property is user input or automated
if m(j).fcn
% run automated custom function for property and display result
m(j).value = nc_kickstarter_customfcn(OPT.host, var, m(j), m);
fprintf('[%s] %s:\n%s\n',upper(m(j).key),m(j).description,m(j).value);
else
% ask for user input
m(j).value = input(sprintf('[%s] %s:\n',upper(m(j).key),m(j).description),'s');
end
% append to query string
query_string = sprintf('%s&m[%s.%s]=%s',query_string,m(j).category,m(j).key,urlencode(m(j).value));
fprintf('\n');
end
n = n + 1;
vars = [vars {var}];
end
%% load data
if OPT.data
% read data and extract properties from it
[m, dims, vars] = nc_kickstarter_data_read(OPT.host, OPT.template, OPT.epsg, vars);
% append to query string
for i = 1:length(m)
query_string = sprintf('%s&m[%s.%s]=%s',query_string,m(i).category,m(i).key,urlencode(m(i).value));
end
fprintf('\n');
% load other categories of properties, not related to variables,
% dimensions or data (already processed)
categories = setdiff(json.load(urlread([OPT.host '/json/categories'])),{'var','dat','dim'});
else
% load categories not related to variables (already processed)
categories = setdiff(json.load(urlread([OPT.host '/json/categories'])),{'var'});
end
%% show other markers
% loop over categories
for i = 1:length(categories)
% show header with category name
fprintf('----------------------------------------\n');
fprintf('%s\n',upper(categories{i}));
fprintf('----------------------------------------\n');
fprintf('\n');
% retrieve all properties to be specified in the current category
url = [OPT.host '/json/templates/' [OPT.template '?category=' categories{i}]];
data = urlread(url);
m = json.load(data);
% loop over properties
for j = 1:length(m)
% check if property value should be stored for later use
if m(j).save
% determine last used property value
pref_key = sprintf('%s_%s',m(j).category,m(j).key);
if ispref(pref_group,pref_key)
v = getpref(pref_group,pref_key);
else
v = '';
end
% ask for user input
v_new = input(sprintf('[%s] %s [%s]:\n',upper(m(j).key),m(j).description,v),'s');
% use last stored value in case no input is given
if ~isempty(v_new)
v = v_new;
end
% store property value for later use
setpref(pref_group,pref_key,v);
else
% ask for user input
v = input(sprintf('[%s] %s:\n',upper(m(j).key),m(j).description),'s');
end
% append to query string
query_string = sprintf('%s&m[%s.%s]=%s',query_string,m(j).category,m(j).key,urlencode(v));
fprintf('\n');
end
end
%% download result
% show file save dialog to store downloaded file
[fname, fpath] = uiputfile( ...
{['*' ext];'*.*'}, ...
'Save file', ...
regexprep(OPT.template,'\.cdl$',ext));
if fname > 0
% built full query for netCDF kickstarter webservice
tmpl_query = [OPT.template '?filename=' OPT.filename query_string];
url = [OPT.host '/' OPT.format '/' tmpl_query];
% download result file
fprintf('Downloading file... ');
ncfile = fullfile(fpath,fname);
urlwrite(url,ncfile);
fprintf('done\n');
fprintf('Saved file to %s\n', ncfile);
fprintf('\n');
% show links to related files (other formats)
fprintf('Related files:\n');
fprintf(' * CDL template\n', [OPT.host '/cdl/' tmpl_query]);
fprintf(' * netCDF file\n', [OPT.host '/netcdf/' tmpl_query]);
fprintf(' * Python script\n', [OPT.host '/python/' tmpl_query]);
fprintf(' * Matlab script\n', [OPT.host '/matlab/' tmpl_query]);
fprintf(' * ncML file\n', [OPT.host '/ncml/' tmpl_query]);
fprintf('\n');
% if data mode is enabled and a netcdf format is chosen, ask if data
% should be added to the netcdf file, otherwise show instructions
if OPT.data && strcmpi(OPT.format,'netcdf') && ismember(lower(input('Add data? [y]: ','s')),{'','y','yes'})
nc_kickstarter_data_add(ncfile, dims, vars);
else
fprintf('To add data to the newly created netCDF file, use the following commands:\n');
fprintf('>> ncfile = ''%s''\n', fullfile(fpath,fname));
fprintf('>> nc_varput(ncfile,''x'',x);\n');
fprintf('>> nc_varput(ncfile,''y'',y);\n');
fprintf('>> nc_varput(ncfile,''z'',z);\n');
end
end
fname = fullfile(fpath,fname);