% generate_OS_EXAMPLEFILE
%
% Time-stamp: <2011-12-05 13:06:28 mlankhorst>
%
% Generic script to create an OceanSITES data file.
%
% OceanSITES data files are netCDF files with a certain metadata
% syntax and general nomenclature requirements. This script is
% meant as an example for use by OceanSITES investigators and data
% centers, who have to assemble OceanSITES data files from data
% that is in a different format. It runs under MatLab and uses the
% netCDF commands that the current version of MatLab comes with.
%
% NOTE: The data variables in this file are randomly generated and
% thereby useless for scientific interpretation. The information in
% the metadata fields is equally artificial. For your own purposes,
% you must insert your data and review the metadata fields one by
% one, replacing the dummies with whatever is appropriate for your
% situation.
%
% Initially created 2011-12-05 by Matthias Lankhorst
%
% See also OceanSITES website at: http://www.oceansites.org
%

function generate_OS_EXAMPLEFILE
  
  fprintf('\n\nStarting OS generator script at %s\n\n', ...
	  datestr(now));
  
  
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  %%%   Dummy data defined here.
  %%%   This script will write these data into
  %%%   an OceanSITES netCDF file.
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  
  % Latitude and longitude
  dat_lat=16;
  dat_lon=-53;
  
  % Time
  dat_tim=datenum(2000,1,1)+[0:19];
  ltim=length(dat_tim);
  
  % Depth
  dat_z=[1000:1000:3000];
  lz=length(dat_z);
  
  % Dummy data (random numbers meant to represent sea water
  % temperature, current speed, and current direction)
  dat_temp=5+randn(lz,ltim);
  dat_cspd=.5.*rand(lz,ltim);
  dat_cdir=360.*rand(lz,ltim);
  
  % Dummy QC data (random integers of the same size as the dummy
  % data)
  dat_temp_qc=round(5.*rand(lz,ltim));
  dat_cspd_qc=round(5.*rand(lz,ltim));
  dat_cdir_qc=round(5.*rand(lz,ltim));
  
  % Output file name (note that file name has to be standardized as
  % per the OceanSITES user manual)
  output_file='OS_EXAMPLEFILE_FORMAT-1-2_D.nc';
  
  
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  %%%   Delete existing file
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  
  if (exist(output_file,'file'))==2
    fprintf('Deleting existing file %s\n',output_file);
    delete(output_file)
  end
  
  fprintf('Creating new file %s\n',output_file);
  nc=netcdf.create(output_file,'CLOBBER');
  netcdf.close(nc);
  
  
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  %%%   Write global attributes
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  
  fprintf('Writing global attributes\n');
  
  ncwriteatt(output_file,'/','data_type', ...
	     'OceanSITES time-series data');
  ncwriteatt(output_file,'/','format_version', ...
	     '1.2');
  ncwriteatt(output_file,'/','platform_code', ...
	     'EXAMPLEFILE');
  ncwriteatt(output_file,'/','date_update', ...
	     datestr(now+8/24,'yyyy-mm-ddTHH:MM:SSZ'));
         % Note: make sure "now+X/24" is in UTC
  ncwriteatt(output_file,'/','institution', ...
	     'my_institution_of_oceanography');
  ncwriteatt(output_file,'/','site_code', ...
	     'EXAMPLEFILE');
  ncwriteatt(output_file,'/','array', ...
	     'EXAMPLEFILE');
  ncwriteatt(output_file,'/','network', ...
	     'EXAMPLEFILE');
  ncwriteatt(output_file,'/','wmo_platform_code', ...
	     '0123456789');
  ncwriteatt(output_file,'/','source', ...
	     'Mooring observation');
  ncwriteatt(output_file,'/','history', ...
	     sprintf('%s generated from scratch by M. Lankhorst', ...
		     datestr(now+8/24,'yyyy-mm-ddTHH:MM:SSZ')));
         % Note: make sure "now+X/24" is in UTC
  ncwriteatt(output_file,'/','data_mode', ...
	     'D');
  ncwriteatt(output_file,'/','quality_control_indicator', ...
	     '5');
  ncwriteatt(output_file,'/','quality_index', ...
	     'A');
  ncwriteatt(output_file,'/','references', ...
	     'http://www.oceansites.org, http://scripps.ucsd.edu');
  ncwriteatt(output_file,'/','comment', ...
	     ['Example data file. All data are random numbers. ', ...
	      'Do not use except as file format template.']);
  ncwriteatt(output_file,'/','Conventions', ...
	     'CF-1.5, OceanSITES 1.2');
  ncwriteatt(output_file,'/','Netcdf_version', ...
	     '3');
  ncwriteatt(output_file,'/','title', ...
	     'Example OceanSITES Data File');
  ncwriteatt(output_file,'/','summary', ...
	     ['Example OceanSITES data file for use by PI or DAC ', ...
	      'as template.']);
  ncwriteatt(output_file,'/','naming_authority', ...
	     'OceanSITES');
  ncwriteatt(output_file,'/','id', ...
	     output_file(1:end-3));
  ncwriteatt(output_file,'/','cdm_data_type', ...
	     'Station');
  ncwriteatt(output_file,'/','area', ...
	     'Tropical Atlantic Ocean');
  ncwriteatt(output_file,'/','geospatial_lat_min', ...
	     num2str(min(dat_lat)));
  ncwriteatt(output_file,'/','geospatial_lat_max', ...
	     num2str(max(dat_lat)));
  ncwriteatt(output_file,'/','geospatial_lon_min', ...
	     num2str(min(dat_lon)));
  ncwriteatt(output_file,'/','geospatial_lon_max', ...
	     num2str(max(dat_lon)));
  ncwriteatt(output_file,'/','geospatial_vertical_min', ...
	     num2str(min(-dat_z)));
  ncwriteatt(output_file,'/','geospatial_vertical_max', ...
	     num2str(max(-dat_z)));
  ncwriteatt(output_file,'/','time_coverage_start', ...
	     datestr(min(dat_tim),'yyyy-mm-ddTHH:MM:SSZ'));
  ncwriteatt(output_file,'/','time_coverage_end', ...
	     datestr(max(dat_tim),'yyyy-mm-ddTHH:MM:SSZ'));
  ncwriteatt(output_file,'/','institution_references', ...
	     'http://scripps.ucsd.edu');
  ncwriteatt(output_file,'/','contact', ...
	     'mlankhorst@ucsd.edu');
  ncwriteatt(output_file,'/','author', ...
	     'Matthias Lankhorst');
  ncwriteatt(output_file,'/','data_assembly_center', ...
	     'NDBC');
  ncwriteatt(output_file,'/','pi_name', ...
	     'Matthias Lankhorst');
  ncwriteatt(output_file,'/','distribution_statement', ...
	     ['http://www.bodc.ac.uk/projects/international/', ...
	      'clivar/data_policy/']);
  ncwriteatt(output_file,'/','citation', ...
	     ['These data were collected and made freely available', ...
	      ' by the OceanSITES project and the national programs', ...
	      ' that contribute to it.']);
  ncwriteatt(output_file,'/','update_interval', ...
	     'void');
  ncwriteatt(output_file,'/','qc_manual', ...
	     'http://www.oceansites.org');
  
  
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  %%%   Write coordinate variables
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  
  fprintf('Writing coordinate variables\n');
  
  nccreate(output_file,'TIME', ...
	   'Dimensions',{'TIME',ltim}, ...
	   'Datatype','double');
  ncwrite(output_file,'TIME', ...
	  dat_tim-datenum(1950,1,1));
  ncwriteatt(output_file,'TIME', ...
	     'long_name','time');
  ncwriteatt(output_file,'TIME', ...
	     'standard_name','time');
  ncwriteatt(output_file,'TIME', ...
	     'units','days since 1950-01-01T00:00:00Z');
  ncwriteatt(output_file,'TIME', ...
	     'valid_min',min(dat_tim));
  ncwriteatt(output_file,'TIME', ...
	     'valid_max',max(dat_tim));
  ncwriteatt(output_file,'TIME', ...
	     'QC_indicator',1);
  ncwriteatt(output_file,'TIME', ...
	     'QC_procedure',5);
  ncwriteatt(output_file,'TIME', ...
	     'uncertainty',.0035);
  ncwriteatt(output_file,'TIME', ...
	     'comment','n/a');
  ncwriteatt(output_file,'TIME', ...
	     'axis','T');
  
  nccreate(output_file,'LATITUDE', ...
	   'Dimensions',{'LATITUDE',1}, ...
	   'Datatype','double');
  ncwrite(output_file,'LATITUDE', ...
	  dat_lat);
  ncwriteatt(output_file,'LATITUDE', ...
	     'long_name','Latitude of each location');
  ncwriteatt(output_file,'LATITUDE', ...
	     'standard_name','latitude');
  ncwriteatt(output_file,'LATITUDE', ...
	     'units','degrees_north');
  ncwriteatt(output_file,'LATITUDE', ...
	     'valid_min',min(dat_lat));
  ncwriteatt(output_file,'LATITUDE', ...
	     'valid_max',max(dat_lat));
  ncwriteatt(output_file,'LATITUDE', ...
	     'QC_indicator',1);
  ncwriteatt(output_file,'LATITUDE', ...
	     'QC_procedure',5);
  ncwriteatt(output_file,'LATITUDE', ...
	     'uncertainty',.004);
  ncwriteatt(output_file,'LATITUDE', ...
	     'comment','n/a');
  ncwriteatt(output_file,'LATITUDE', ...
	     'axis','Y');
  ncwriteatt(output_file,'LATITUDE', ...
	     'reference','WGS84');
  
  nccreate(output_file,'LONGITUDE', ...
	   'Dimensions',{'LONGITUDE',1}, ...
	   'Datatype','double');
  ncwrite(output_file,'LONGITUDE', ...
	  dat_lon);
  ncwriteatt(output_file,'LONGITUDE', ...
	     'long_name','Longitude of each location');
  ncwriteatt(output_file,'LONGITUDE', ...
	     'standard_name','longitude');
  ncwriteatt(output_file,'LONGITUDE', ...
	     'units','degrees_east');
  ncwriteatt(output_file,'LONGITUDE', ...
	     'valid_min',min(dat_lon));
  ncwriteatt(output_file,'LONGITUDE', ...
	     'valid_max',max(dat_lon));
  ncwriteatt(output_file,'LONGITUDE', ...
	     'QC_indicator',1);
  ncwriteatt(output_file,'LONGITUDE', ...
	     'QC_procedure',5);
  ncwriteatt(output_file,'LONGITUDE', ...
	     'uncertainty',.004);
  ncwriteatt(output_file,'LONGITUDE', ...
	     'comment','n/a');
  ncwriteatt(output_file,'LONGITUDE', ...
	     'axis','X');
  ncwriteatt(output_file,'LONGITUDE', ...
	     'reference','WGS84');
  
  nccreate(output_file,'DEPTH', ...
	   'Dimensions',{'DEPTH',lz}, ...
	   'Datatype','double');
  ncwrite(output_file,'DEPTH', ...
	  dat_z);
  ncwriteatt(output_file,'DEPTH', ...
	     'long_name','Depth of each measurement');
  ncwriteatt(output_file,'DEPTH', ...
	     'standard_name','depth');
  ncwriteatt(output_file,'DEPTH', ...
	     'units','meters');
  ncwriteatt(output_file,'DEPTH', ...
	     'positive','down');
  ncwriteatt(output_file,'DEPTH', ...
	     'valid_min',min(dat_z));
  ncwriteatt(output_file,'DEPTH', ...
	     'valid_max',max(dat_z));
  ncwriteatt(output_file,'DEPTH', ...
	     'QC_indicator',1);
  ncwriteatt(output_file,'DEPTH', ...
	     'QC_procedure',5);
  ncwriteatt(output_file,'DEPTH', ...
	     'uncertainty',50);
  ncwriteatt(output_file,'DEPTH', ...
	     'comment','n/a');
  ncwriteatt(output_file,'DEPTH', ...
	     'axis','Z');
  ncwriteatt(output_file,'DEPTH', ...
	     'reference','mean_sea_level');
  
  
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  %%%   Write data variables
  %%%
  %%% Note: the manual allows an alternative implementation
  %%% of uncertainty and data mode as time-dependent
  %%% variables, much like TEMP_QC used here (and vice
  %%% versa, QC could be implemented as one constant
  %%% attribute if that were more appropriate).
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  
  fprintf('Writing data variables\n');
  
  nccreate(output_file,'TEMP', ...
	   'Dimensions',{'TIME',ltim,'DEPTH',lz}, ...
	   'Datatype','double');
  ncwrite(output_file,'TEMP',dat_temp');
  ncwriteatt(output_file,'TEMP', ...
	     'long_name','sea water temperature');
  ncwriteatt(output_file,'TEMP', ...
	     'standard_name','sea_water_temperature');
  ncwriteatt(output_file,'TEMP','units','degree_Celsius');
  ncwriteatt(output_file,'TEMP','QC_procedure','5');
  ncwriteatt(output_file,'TEMP','valid_min',-2.5);
  ncwriteatt(output_file,'TEMP','valid_max',40);
  ncwriteatt(output_file,'TEMP', ...
	     'comment','In-situ measurement');
  ncwriteatt(output_file,'TEMP','sensor_depth',dat_z);
  ncwriteatt(output_file,'TEMP', ...
	     'sensor_name','Sensor Make and Model');
  ncwriteatt(output_file,'TEMP', ...
	     'sensor_serial_number','1 2 3');
  ncwriteatt(output_file,'TEMP','ancillary_variables','TEMP_QC');
  ncwriteatt(output_file,'TEMP','uncertainty',0.01);
  ncwriteatt(output_file,'TEMP','accuracy',0.005);
  ncwriteatt(output_file,'TEMP','precision',0.001);
  ncwriteatt(output_file,'TEMP','resolution',0.0001);
  ncwriteatt(output_file,'TEMP','cell_methods', ...
	     ['TIME: point DEPTH: point ', ...
	      'LATITUDE: point LONGITUDE: point']);
  ncwriteatt(output_file,'TEMP','DM_indicator','D');
  ncwriteatt(output_file,'TEMP','reference_scale','ITS-90');
  
  
  nccreate(output_file,'TEMP_QC', ...
	   'Dimensions',{'TIME',ltim,'DEPTH',lz}, ...
	   'Datatype','int8');
  ncwrite(output_file,'TEMP_QC',int8(dat_temp_qc'));
  ncwriteatt(output_file,'TEMP_QC','long_name','quality flag');
  ncwriteatt(output_file,'TEMP_QC','conventions', ...
	     'OceanSITES reference table 2');
  ncwriteatt(output_file,'TEMP_QC','valid_min',int8(0));
  ncwriteatt(output_file,'TEMP_QC','valid_max',int8(9));
  ncwriteatt(output_file,'TEMP_QC','flag_values', ...
	     int8([0,1,2,3,4,5,7,8,9]));
  ncwriteatt(output_file,'TEMP_QC','flag_meanings', ...
	     ['no_qc_performed good_data probably_good_data ', ...
	      'bad_data_that_are_potentially_correctable ', ...
	      'bad_data value_changed nominal_value ', ...
	      'interpolated_value missing_value']);
  
  
  nccreate(output_file,'CSPD', ...
	   'Dimensions',{'TIME',ltim,'DEPTH',lz}, ...
	   'Datatype','double');
  ncwrite(output_file,'CSPD',dat_cspd');
  ncwriteatt(output_file,'CSPD', ...
	     'long_name','sea water speed');
  ncwriteatt(output_file,'CSPD', ...
	     'standard_name','sea_water_speed');
  ncwriteatt(output_file,'CSPD','units','m s-1');
  ncwriteatt(output_file,'CSPD','QC_procedure','5');
  ncwriteatt(output_file,'CSPD','valid_min',0);
  ncwriteatt(output_file,'CSPD','valid_max',1);
  ncwriteatt(output_file,'CSPD', ...
	     'comment','In-situ measurement');
  ncwriteatt(output_file,'CSPD','sensor_depth',dat_z);
  ncwriteatt(output_file,'CSPD', ...
	     'sensor_name','Sensor Make and Model');
  ncwriteatt(output_file,'CSPD', ...
	     'sensor_serial_number','1 2 3');
  ncwriteatt(output_file,'CSPD','ancillary_variables','CSPD_QC');
  ncwriteatt(output_file,'CSPD','uncertainty',0.01);
  ncwriteatt(output_file,'CSPD','accuracy',0.005);
  ncwriteatt(output_file,'CSPD','precision',0.001);
  ncwriteatt(output_file,'CSPD','resolution',0.0001);
  ncwriteatt(output_file,'CSPD','cell_methods', ...
	     ['TIME: point DEPTH: point ', ...
	      'LATITUDE: point LONGITUDE: point']);
  ncwriteatt(output_file,'CSPD','DM_indicator','D');
  
  
  nccreate(output_file,'CSPD_QC', ...
	   'Dimensions',{'TIME',ltim,'DEPTH',lz}, ...
	   'Datatype','int8');
  ncwrite(output_file,'CSPD_QC',int8(dat_cspd_qc'));
  ncwriteatt(output_file,'CSPD_QC','long_name','quality flag');
  ncwriteatt(output_file,'CSPD_QC','conventions', ...
	     'OceanSITES reference table 2');
  ncwriteatt(output_file,'CSPD_QC','valid_min',int8(0));
  ncwriteatt(output_file,'CSPD_QC','valid_max',int8(9));
  ncwriteatt(output_file,'CSPD_QC','flag_values', ...
	     int8([0,1,2,3,4,5,7,8,9]));
  ncwriteatt(output_file,'CSPD_QC','flag_meanings', ...
	     ['no_qc_performed good_data probably_good_data ', ...
	      'bad_data_that_are_potentially_correctable ', ...
	      'bad_data value_changed nominal_value ', ...
	      'interpolated_value missing_value']);
  
  
  nccreate(output_file,'CDIR', ...
	   'Dimensions',{'TIME',ltim,'DEPTH',lz}, ...
	   'Datatype','double');
  ncwrite(output_file,'CDIR',dat_cdir');
  ncwriteatt(output_file,'CDIR', ...
	     'long_name','direction of sea water velocity');
  ncwriteatt(output_file,'CDIR', ...
	     'standard_name','direction_of_sea_water_velocity');
  ncwriteatt(output_file,'CDIR','units','degree');
  ncwriteatt(output_file,'CDIR','QC_procedure','5');
  ncwriteatt(output_file,'CDIR','valid_min',0);
  ncwriteatt(output_file,'CDIR','valid_max',360);
  ncwriteatt(output_file,'CDIR','comment', ...
	     ['In-situ measurement. Has magnetic variation ', ...
	      'of -8 degrees applied']);
  ncwriteatt(output_file,'CDIR','sensor_depth',dat_z);
  ncwriteatt(output_file,'CDIR', ...
	     'sensor_name','Sensor Make and Model');
  ncwriteatt(output_file,'CDIR', ...
	     'sensor_serial_number','1 2 3');
  ncwriteatt(output_file,'CDIR','ancillary_variables','CDIR_QC');
  ncwriteatt(output_file,'CDIR','uncertainty',3);
  ncwriteatt(output_file,'CDIR','accuracy',2);
  ncwriteatt(output_file,'CDIR','precision',0.2);
  ncwriteatt(output_file,'CDIR','resolution',0.01);
  ncwriteatt(output_file,'CDIR','cell_methods', ...
	     ['TIME: point DEPTH: point ', ...
	      'LATITUDE: point LONGITUDE: point']);
  ncwriteatt(output_file,'CDIR','DM_indicator','D');
  
  
  nccreate(output_file,'CDIR_QC', ...
	   'Dimensions',{'TIME',ltim,'DEPTH',lz}, ...
	   'Datatype','int8');
  ncwrite(output_file,'CDIR_QC',int8(dat_cdir_qc'));
  ncwriteatt(output_file,'CDIR_QC','long_name','quality flag');
  ncwriteatt(output_file,'CDIR_QC','conventions', ...
	     'OceanSITES reference table 2');
  ncwriteatt(output_file,'CDIR_QC','valid_min',int8(0));
  ncwriteatt(output_file,'CDIR_QC','valid_max',int8(9));
  ncwriteatt(output_file,'CDIR_QC','flag_values', ...
	     int8([0,1,2,3,4,5,7,8,9]));
  ncwriteatt(output_file,'CDIR_QC','flag_meanings', ...
	     ['no_qc_performed good_data probably_good_data ', ...
	      'bad_data_that_are_potentially_correctable ', ...
	      'bad_data value_changed nominal_value ', ...
	      'interpolated_value missing_value']);
  
  
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  %%%  Display file content for double-checking
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  
  fprintf('\nFile has been generated.\n')
  pause(2)
  
  fprintf(['\n\nDisplaying contents of file %s\n\n', ...
	   '****************************************\n\n'], ...
	  output_file);
  
  ncdisp(output_file)
  
  fprintf(['\n****************************************\n\n', ...
	   '[End of contents of file %s]\n\n\n'], ...
	  output_file);
  
  fprintf('Finishing OS generator script at %s\n\n\n', ...
	  datestr(now));
