function aqa2cdf(metaFile, outFileRoot) % aqa2cdf.m A function to convert Aquascat ABS data (*.aqa and *.aqf) to % netCDF. % % usage: aqa2cdf(metaFile, outFileRoot); % % where: metaFile is the name of your text file containing metadata, % surrounded by single quotes WITHOUT the file % extension .txt. An example metadata file, % absmetaexample.txt, is provided in this package of % mfiles. % outFileRoot is the name given to the output netCDF files, % surrounded by single quotes WITHOUT the file % extension .cdf. Output files will be named: % 'outFileRoot'abs(1...n)b.cdf for burst netcdf % files where (1...n) denotes % data subsets % 'outFileRoot'abss.cdf for stats netcdf file % % Written by Charlene Sullivan % USGS Woods Hole Field Center % csullivan@usgs.gov % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Use of this program is self described. % Program written in Matlab v7.1.0 SP3 % Program ran on PC with Windows XP Professional OS. % % "Although this program has been used by the USGS, no warranty, % expressed or implied, is made by the USGS or the United States % Government as to the accuracy and functioning of the program % and related program material nor shall the fact of distribution % constitute any such warranty, and no responsibility is assumed % by the USGS in connection therewith." %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % Dependencies: % readaqa_oleg.m (O. Mouraenko) % matpctile.m (C. Sherwood) % julian.m % gregorian.m % TODO: Read frequencies from 'ABS_info' variable if they're not specified % in the user's metadata file % TODO: Correct the valid range attribute % TODO: Is the use of floats necessary for the ABS burst files? These % contain integer values. % C. Sullivan 03/21/06, version 1.6 % Add latitude and longitude variables to burst and statistic netcdf files. % Run code with Matlab R2006a to check for compatibility issues, and use % M-lint code analyzer for suggestions on how to improve code speed. % C. Sullivan 08/22/05, version 1.5 % Add capeability to process USC ABS data. Read this data with % read_aquatec_v4.m. This code is a modified form of the code % read_aquatec_V3_2.m provided by G. Voulgaris (USC). Include metadata % output to 'ABS_info' by readaqa_oleg.m and read_aquatec_v4.m in metadata. % Change netcdf variables 'Mdata*' to 'abs_trans*'. % C. Sullivan 07/11/05, version 1.4 % Add the attributes 'input_directory', 'output_directory', and 'Conventions' % to the metadata file. Users should place their metadata file in the % directory specified by the attribute 'output_directory', and run this % mfile from that directory. Remove the attributes 'SampleRate', 'SerialNumber', % 'BuildDate', 'DSPVersion', and 'FPGAVersion' from the metadata file because % these attributes will be read from the .aq(a)(f) files. Removing median % variable form statistics netCDF file b/c these values are given by the 50th % percentile. % C. Sullivan 07/07/05, version 1.3 % Some netCDF files are not being closed appropriately. Getting rid of % 'isunix' loop for finding files as we can use the 'dir' command on both % unix and windows with the same result. % C. Sullivan 07/05/05, version 1.2 % This version assumes the user has deleted extra .aqa or .aqf files that % were collected prior to (after) instrument deployment (recovery). We cannot % get burst number from 'ABS_info.burstnum', output by readaqa_oleg.m, because % these are not sequentially numbered from 1:nBursts. For example, the 300th % .aqa file has an ABS_info.burstnum=44 and ABS_info.burstnum appears to % repeats after every 255th burst. % C. Sullivan 07/01/05, version 1.1 % Calculate percentiles for the statistics netCDF file. Calculate statistics % using both the raw amplitudes and the raw amplitudes squared. This version % will also load ABS data downloaded from the instrument as a series of % *.aqa and/or *.aqf files. % C. Sullivan 06/28/05, version 1.0 % This function converts ABS data, downloaded from the instrument as a series % of *.aqa files, to raw data burst and statistic netCDF (*.cdf) files. It % assumes all metadata is defined in a simple text file (see absmetaexample.txt), % and the user is reading a USGS ABS with the mfile readaqa_oleg.m. A maximum % size limit of 500 MB is imposed on the burst netCDF files, therefore there % may be multiple burst netCDF files created. It has been possible to write % all the statistics to a single statistics netCDF file. more off version = '1.6'; % Check for metadata file metaPath = pwd; meta = dir([metaFile,'.txt']); if isempty(meta) fprintf('\n') fprintf('The metadata file %s.txt does not exist in this directory\n',metaFile) metaPath = input('Please enter the full path to the directory with your metadata file: ','s'); meta = dir(fullfile(metaPath,[metaFile,'.txt'])); if isempty(meta) error(['Still cannot find the metadata file ',fullfile(metaPath,[metaFile,'.txt'])]) end end metaFile = fullfile(metaPath,meta.name); % Get user's metadata structure userMeta = readAbsMeta(metaFile); % Check for Aquascat files inputDir = userMeta.input_directory; aqa = dir(fullfile(inputDir,'*.aqa')); aqf = dir(fullfile(inputDir,'*.aqf')); if isempty(aqa) && isempty(aqf) fprintf('\n') error(['Aquascat ABS data files do not exist in ',pwd]); else if ~isempty(aqa) nFiles = length(aqa); aqaFiles = struct([]); for n = 1:nFiles aqaFiles{n} = aqa(n).name; end end if ~isempty(aqf) nFiles = length(aqf); aqfFiles = struct([]); for n = 1:nFiles aqfFiles{n} = aqf(n).name; end end if ~isempty(aqa) && ~isempty(aqf) aqFiles = char(union(aqaFiles,aqfFiles)); elseif ~isempty(aqf) aqFiles = char(aqfFiles); elseif ~isempty(aqa) aqFiles = char(aqaFiles); end nAqFiles = size(aqFiles,1); end % Determine which mfile will read the Aquascat files testFile = fullfile(inputDir,aqFiles(1,:)); try %WH ABS disp(' ') disp('Determining how to read Aquascat data files') disp('Trying to read data with readaqa_oleg.m') disp(' ') [absMeta, absData] = readaqa_oleg(testFile); disp(' ') disp('readaqa_oleg.m sucessful') disp('Data will be read with readaqa_oleg.m') readAbsMfile = 'readaqa_oleg'; catch try %USC ABS disp(' ') disp('readaqa_oleg.m failed. Trying to read data with read_aquatec_v4.m') [absMeta, absData]=read_aquatec_v4(testFile); disp(' ') disp('read_aquatec_v4.m successful') disp('Data will be read with read_aquatec_v4.m') readAbsMfile = 'read_aquatec_v4'; catch error('Could not read data with readaqa_oleg.m or read_aquatec_v4.m') end end % The 1st, 15th, 50th, 84th, and 99th percentiles will be calculated for % the statistics file. Include this information in the user's metadata. pctiles = [1; 16; 50; 84; 99]; userMeta.pctiles = pctiles'; userMeta.nPctiles = length(userMeta.pctiles); % There is a 500 MB size limit imposed on the raw data burst netCDF (.cdf) % files. Additional raw data burst netCDF files are created as needed. maxBytes = 500000000; burstFileNum = 1; %initialize burst netcdf file # lastBrec = 0; %initialize burst record # tic % The following loop reads the data in each Aquascat data file, writes the % burst data to the burst netCDF file, performs basic statistics on the % burst, and writes the statistics to the statistics netCDF file. for n = 1:nAqFiles aqFile = fullfile(inputDir,aqFiles(n,:)); %burst file name brec = n - lastBrec; %burst record number srec = n; %statistic record number %Read the data switch readAbsMfile case 'readaqa_oleg' [absMeta, absData] = readaqa_oleg(aqFile); %WH ABS case 'read_aquatec_v4' [absMeta, absData]=read_aquatec_v4(aqFile); %USC ABS end %Clean up fields in 'userMeta' if ~isfield(userMeta,'serial_number') && ... isfield(absMeta,'sysinfo') userMeta.serial_number = absMeta.sysinfo(23:29); end %Clean up the fields in 'absMeta' if isfield(absMeta,'ProfileRate') absMeta.samp_rate = absMeta.ProfileRate; absMeta = rmfield(absMeta,'ProfileRate'); end if isfield(absMeta,'Averaging1') absMeta.avg_over = absMeta.Averaging1; absMeta = rmfield(absMeta,'Averaging1'); end absMeta = rmfield(absMeta,{'year','month','day',... 'hour','minute','second'}); %Add fields to 'absMeta' to specify dimensions absMeta.nBins = size(absData.mdata,1); %number of bins absMeta.nProfiles = size(absData.mdata,2); %number of profiles absMeta.nXducers = size(absData.r,2); %number of xducers %Write fields in 'userMeta' and 'absMeta' to a new structure, %'allMeta'. All fields in 'allMeta' are written to the netcdf %files as global attributes. usrFields = fieldnames(userMeta); for f = 1:size(usrFields,1) eval(['allMeta.',usrFields{f},' = userMeta.',usrFields{f},';']) end absFields = fieldnames(absMeta); for f = 1:size(absFields,1) eval(['allMeta.',absFields{f},' = absMeta.',absFields{f},';']) end if n == 1 %Create burst and statistic netCDF files [cdfb, burstFile] = defineAbsBurstCdf(allMeta, outFileRoot, burstFileNum); [cdfs, statFile] = defineAbsStatCdf(allMeta, outFileRoot); fprintf('\n') fprintf('There are %d bursts to write to netCDF\n',nAqFiles) fprintf('Writing burst data to the file %s\n',burstFile) fprintf('Writing statistics data to the file %s\n',statFile) %Extract dimensions. These are constant for each %Aquascat file, so extract them once at the start. binDim = cdfb('bin'); nBins = size(binDim,1); profDim = cdfb('profile'); nProfiles = size(profDim,1); xducerDim = cdfb('xducer'); nXducers = size(xducerDim,1); pctlDim = cdfs('pctile'); nPctiles = size(pctlDim,1); %Some index variables are constant for each Aquascat %file, so write these only once at the beginning. cdfb{'r'}(1:nBins,1:nXducers) = absData.r / 1000; %Distance from the ABS, m cdfs{'r'}(1:nBins,1:nXducers) = absData.r / 1000; cdfs{'pctile'}(1:nPctiles) = pctiles; %Percentiles end %Write Aquascat data to the burst netCDF file profStartTime = julian(datevec(absData.sdatenum)); % profile start time, julian days sampleRate = absMeta.samp_rate; %sample rate samples_per_avg = absMeta.avg_over; %samples per average profDt = (1/(sampleRate/samples_per_avg))/3600/24; profTime = profStartTime : profDt : profStartTime+(profDt*(nProfiles-1)); cdfb{'time'}(brec, 1:nProfiles) = floor(profTime); cdfb{'time2'}(brec, 1:nProfiles) = (profTime-floor(profTime)).*(24*3600*1000); if ~isequal(absMeta.burstnum,n) %if burst #'s begin to repeat, cdfb{'burst'}(brec) = n; %override them else cdfb{'burst'}(brec) = absMeta.burstnum; end cdfb{'abs_trans1'}(brec, 1:nProfiles, 1:nBins) = absData.mdata(:,:,1)'; %Amplitude at frequency 1 cdfb{'abs_trans2'}(brec, 1:nProfiles, 1:nBins) = absData.mdata(:,:,2)'; %Ampliude at frequency 2 cdfb{'abs_trans3'}(brec, 1:nProfiles, 1:nBins) = absData.mdata(:,:,3)'; %Ampliude at frequency 3 %Get the size of the burst netCDF file after the %1st Aquascat file is written. Use this size to determine %the number of Aquascat files you can write to each %burst netCDF file if n == 1 filechk = dir(burstFile); bytesPerAqFile = filechk.bytes; nAqFilesPerBurstCdf = floor(maxBytes/bytesPerAqFile); end %write statistics to the statistic netCDF file cdfs{'time'}(srec) = floor(profTime(1));%use first time stamp in each burst cdfs{'time2'}(srec) = (profTime(1)-floor(profTime(1))).*(24*3600*1000); if ~isequal(absMeta.burstnum,n) %if burst #'s begin to repeat, cdfs{'burst'}(srec) = n; %override them else cdfs{'burst'}(srec) = absMeta.burstnum; end cdfs{'abs_trans1_mean'}(srec, 1:nBins) = mean(absData.mdata(:,:,1),2)'; cdfs{'abs_trans2_mean'}(srec, 1:nBins) = mean(absData.mdata(:,:,2),2)'; cdfs{'abs_trans3_mean'}(srec, 1:nBins) = mean(absData.mdata(:,:,3),2)'; cdfs{'abs_trans1_mean_sq'}(srec, 1:nBins) = mean(absData.mdata(:,:,1)'.^2); cdfs{'abs_trans2_mean_sq'}(srec, 1:nBins) = mean(absData.mdata(:,:,2)'.^2); cdfs{'abs_trans3_mean_sq'}(srec, 1:nBins) = mean(absData.mdata(:,:,3)'.^2); cdfs{'abs_trans1_std'}(srec, 1:nBins) = std(absData.mdata(:,:,1),0,2)'; cdfs{'abs_trans2_std'}(srec, 1:nBins) = std(absData.mdata(:,:,2),0,2)'; cdfs{'abs_trans3_std'}(srec, 1:nBins) = std(absData.mdata(:,:,3),0,2)'; cdfs{'abs_trans1_std_sq'}(srec, 1:nBins) = std(absData.mdata(:,:,1)'.^2); cdfs{'abs_trans2_std_sq'}(srec, 1:nBins) = std(absData.mdata(:,:,2)'.^2); cdfs{'abs_trans3_std_sq'}(srec, 1:nBins) = std(absData.mdata(:,:,3)'.^2); cdfs{'abs_trans1_pctl'}(srec, 1:nBins, 1:nPctiles) = matpctile(absData.mdata(:,:,1)', pctiles)'; cdfs{'abs_trans2_pctl'}(srec, 1:nBins, 1:nPctiles) = matpctile(absData.mdata(:,:,2)', pctiles)'; cdfs{'abs_trans3_pctl'}(srec, 1:nBins, 1:nPctiles) = matpctile(absData.mdata(:,:,3)', pctiles)'; cdfs{'abs_trans1_pctl_sq'}(srec, 1:nBins, 1:nPctiles) = matpctile(absData.mdata(:,:,1)'.^2, pctiles)'; cdfs{'abs_trans2_pctl_sq'}(srec, 1:nBins, 1:nPctiles) = matpctile(absData.mdata(:,:,2)'.^2, pctiles)'; cdfs{'abs_trans3_pctl_sq'}(srec, 1:nBins, 1:nPctiles) = matpctile(absData.mdata(:,:,3)'.^2, pctiles)'; %Update the user with the code's progress if mod(n,50)==0 fprintf('Finished writing burst %d; %6.2f minutes elapsed\n',... n,toc/60) end %If n equals the number of bursts you can write to the burst netCDF %file, close this burst netCDF file and create another one to which %you will write subsequent bursts if mod(n,nAqFilesPerBurstCdf)==0 lastBrec = cdfb{'burst'}(end); %Write latitude and longtitude variables once at the end cdfb{'lat'}(:) = cdfb.latitude(:); cdfb{'lon'}(:) = cdfb.longtiude(:); %Update the attributes of the current burst netCDF file fprintf('The burst file %s is full\n',burstFile) cdfb.burstnum = []; start_time = cdfb{'time'}(1,1) + cdfb{'time2'}(1,1)/3600/1000/24; cdfb.start_time = ncchar(datestr(gregorian(start_time))); stop_time = cdfb{'time'}(end,end) + cdfb{'time2'}(end,end)/3600/1000/24; cdfb.stop_time = ncchar(datestr(gregorian(stop_time))); hist = cdfb.history(:); hist_new = ['Converted to netCDF via Matlab by aqa2cdf.m V ',version,'; ',hist]; cdfb.history = ncchar(hist_new); cdfb=close(cdfb); %Create a new burst netCDF file for subsequent bursts burstFileNum = burstFileNum + 1; [cdfb, burstFile] = defineAbsBurstCdf(allMeta, outFileRoot, burstFileNum); fprintf('Now writing burst data to the file %s\n',burstFile) cdfb{'r'}(1:nBins,1:nXducers) = absData.r / 1000; %Distance from the ABS, m end if mod(n,nAqFiles)==0 cdfb.burstnum = []; %Write latitude and longtitude variables once at the end cdfb{'lat'}(:) = cdfb.latitude(:); cdfb{'lon'}(:) = cdfb.longtiude(:); %Update the attributes of the last burst netCDF file start_time = cdfb{'time'}(1,1) + cdfb{'time2'}(1,1)/3600/1000/24; cdfb.start_time = ncchar(datestr(gregorian(start_time))); stop_time = cdfb{'time'}(end,end) + cdfb{'time2'}(end,end)/3600/1000/24; cdfb.stop_time = ncchar(datestr(gregorian(stop_time))); hist = cdfb.history(:); hist_new = ['Converted to netCDF via Matlab by aqa2cdf.m V ',version,'; ',hist]; cdfb.history = ncchar(hist_new); cdfb=close(cdfb); %update the attributes of the statistics netCDF file and %calculate min/max values cdfs.burstnum = []; %Write latitude and longtitude variables once at the end cdfs{'lat'}(:) = cdfs.latitude(:); cdfs{'lon'}(:) = cdfs.longtiude(:); start = cdfs{'time'}(1) + cdfs{'time2'}(1)/3600/1000/24; cdfs.start_time = ncchar(datestr(gregorian(start))); stop = cdfs{'time'}(end) + cdfs{'time2'}(end)/3600/1000/24; cdfs.stop_time = ncchar(datestr(gregorian(stop))); delta_t = mean(diff(cdfs{'time'}(:) + cdfs{'time2'}(:)/3600/1000/24)); cdfs.DELTA_T = ncchar([num2str(delta_t*24*3600),' s']); hist = cdfs.history(:); hist_new = ['Converted to netCDF via Matlab by aqa2cdf.m V ',version,'; ',hist]; cdfs.history = ncchar(hist_new); calc_minmax_vals(cdfs); cdfs=close(cdfs); fprintf('Finished writing all bursts. %6.2f minutes elapsed\n',toc/60) end end % ---------------------- Subfunction ------------------------------------ % function userMeta = readAbsMeta(metaFile) [atts, defs] = textread(metaFile,'%s %63c','commentstyle','shell'); defs = cellstr(defs); for i = 1:length(atts) theAtt = atts{i}(:)'; theDef = defs{i}(:)'; % deblank removes trailing whitespace theAtt = deblank(theAtt); theDef = deblank(theDef); % check for and replace spaces in % the attributes with underscores f1 = find(isspace(theAtt)); f2 = strfind(theAtt,'-'); f = union(f1,f2); if ~isempty(f) theAtt(f) = '_'; end % attribute definitions read in as characters; convert to % numbers where appropriate theDefNum = str2double(theDef); if ~isnan(theDefNum) theDef = theDefNum; end userMeta.(theAtt) = theDef; end % ---------------------- Subfunction ------------------------------------ % function [cdfb, burstFile] = defineAbsBurstCdf(userMeta, outFileRoot, burstFileNum) outputDir = userMeta.output_directory; burstFileNum = num2str(burstFileNum); burstFile = fullfile(outputDir,[outFileRoot,burstFileNum,'b.cdf']); cdfb = netcdf(burstFile,'clobber'); % write metadata metaFields = fieldnames(userMeta); for i = 1:length(metaFields) theField = metaFields{i}; theFieldDef = userMeta.(theField); nRows = size(theFieldDef,1); nCols = size(theFieldDef,2); temp = []; if nRows>1 for ii = 1:nRows temp = [temp,' ',theFieldDef(ii,1:nCols)]; end theFieldDef = temp; end if ~strcmp(theField,'bins') && ... %don't write these attributes b/c ~strcmp(theField,'freqs') && ... %they are not read from the .aqa files correctly ~strcmp(theField,'gains') %and their information is provided in other attributes cdfb.(theField) = theFieldDef; end end % write additional metadata cdfb.CREATION_DATE = ncchar(datestr(now)); cdfb.DESCRIPT = ncchar('Aquascat ABS raw data burst file'); cdfb.DATA_TYPE = ncchar('ABS'); % define dimensions cdfb('burst') = 0; %unlimited cdfb('profile') = userMeta.nProfiles; cdfb('bin') = userMeta.nBins; cdfb('xducer') = userMeta.nXducers; % define burst variables cdfb{'time'} = nclong('burst','profile'); cdfb{'time'}.FORTRAN_format = ncchar('F10.2'); cdfb{'time'}.units = ncchar('True Julian Day'); cdfb{'time'}.type = ncchar('EVEN'); cdfb{'time'}.epic_code = nclong(624); cdfb{'time'}.FillValue_ = nclong(0); cdfb{'time2'} = nclong('burst','profile') ; cdfb{'time2'}.FORTRAN_format = ncchar('F10.2'); cdfb{'time2'}.units = ncchar('msec since 0:00 GMT'); cdfb{'time2'}.type = ncchar('EVEN'); cdfb{'time2'}.epic_code = nclong(624); cdfb{'time2'}.FillValue_ = nclong(0); cdfb{'burst'} = nclong('burst'); cdfb{'burst'}.FORTRAN_format = ncchar('F10.2'); cdfb{'burst'}.units = ncchar('counts'); cdfb{'burst'}.type = ncchar('EVEN'); cdfb{'burst'}.FillValue_ = nclong(0); cdfb{'lat'} = ncfloat('lat'); cdfb{'lat'}.FORTRAN_format = ncchar('F10.4'); cdfb{'lat'}.units = ncchar('degree_north'); cdfb{'lat'}.type = ncchar('EVEN'); cdfb{'lat'}.epic_code = nclong(500); cdfb{'lon'} = ncfloat('lon'); cdfb{'lon'}.FORTRAN_format = ncchar('F10.4'); cdfb{'lon'}.units = ncchar('degree_east'); cdfb{'lon'}.type = ncchar('EVEN'); cdfb{'lon'}.epic_code = nclong(502); cdfb{'r'} = ncfloat('bin','xducer'); cdfb{'r'}.long_name = ncchar('Distance from ABS sensor head (m)'); cdfb{'r'}.units = ncchar('m'); cdfb{'r'}.valid_range = ncfloat([0 5000]); cdfb{'r'}.sensor_type = cdfb.INST_TYPE(:); cdfb{'r'}.height = ncchar([num2str(cdfb.sensor_height(:)),' m']); cdfb{'r'}.serial = ncchar(cdfb.SerialNumber(:)); cdfb{'r'}.FORTRAN_format = ncchar('F10.2'); cdfb{'r'}.FillValue_ = ncfloat(1.00000004091848e+035); cdfb{'abs_trans1'} = ncfloat('burst','profile','bin'); cdfb{'abs_trans1'}.long_name = ncchar(['Amplitude at ',num2str(cdfb.frequency1(:)),' Mhz']); cdfb{'abs_trans1'}.units = ncchar('ABS units'); cdfb{'abs_trans1'}.valid_range = ncfloat([0 1e16]); cdfb{'abs_trans1'}.sensor_type = cdfb.INST_TYPE(:); cdfb{'abs_trans1'}.height = ncchar([num2str(cdfb.sensor_height(:)),' m']); cdfb{'abs_trans1'}.serial = ncchar(cdfb.serial_number(:)); cdfb{'abs_trans1'}.frequency = ncchar([num2str(cdfb.frequency1(:)),' Mhz']); cdfb{'abs_trans1'}.FORTRAN_format = ncchar('F10.2'); cdfb{'abs_trans1'}.epic_code = 1900; cdfb{'abs_trans1'}.FillValue_ = ncfloat(1.00000004091848e+035); cdfb{'abs_trans2'} = ncfloat('burst','profile','bin'); cdfb{'abs_trans2'}.long_name = ncchar(['Amplitude at ',num2str(cdfb.frequency2(:)),' Mhz']); cdfb{'abs_trans2'}.units = ncchar('ABS units'); cdfb{'abs_trans2'}.valid_range = ncfloat([0 1e16]); cdfb{'abs_trans2'}.sensor_type = cdfb.INST_TYPE(:); cdfb{'abs_trans2'}.height = ncchar([num2str(cdfb.sensor_height(:)),' m']); cdfb{'abs_trans2'}.serial = ncchar(cdfb.serial_number(:)); cdfb{'abs_trans2'}.frequency = ncchar([num2str(cdfb.frequency2(:)),' Mhz']); cdfb{'abs_trans2'}.FORTRAN_format = ncchar('F10.2'); cdfb{'abs_trans2'}.epic_code = 1900; cdfb{'abs_trans2'}.FillValue_ = ncfloat(1.00000004091848e+035); cdfb{'abs_trans3'} = ncfloat('burst','profile','bin'); cdfb{'abs_trans3'}.long_name = ncchar(['Amplitude at ',num2str(cdfb.frequency3(:)),' Mhz']); cdfb{'abs_trans3'}.units = ncchar('ABS units'); cdfb{'abs_trans3'}.valid_range = ncfloat([0 1e16]); cdfb{'abs_trans3'}.sensor_type = cdfb.INST_TYPE(:); cdfb{'abs_trans3'}.height = ncchar([num2str(cdfb.sensor_height(:)),' m']); cdfb{'abs_trans3'}.serial = ncchar(cdfb.serial_number(:)); cdfb{'abs_trans3'}.frequency = ncchar([num2str(cdfb.frequency3(:)),' Mhz']); cdfb{'abs_trans3'}.FORTRAN_format = ncchar('F10.2'); cdfb{'abs_trans3'}.epic_code = 1900; cdfb{'abs_trans3'}.FillValue_ = ncfloat(1.00000004091848e+035); endef(cdfb) return % ---------------------- Subfunction ------------------------------------ % function [cdfs, statFile] = defineAbsStatCdf(userMeta, outFileRoot) outputDir = userMeta.output_directory; statFile = fullfile(outputDir,[outFileRoot,'s.cdf']); cdfs = netcdf(statFile,'clobber'); % write metadata metaFields = fieldnames(userMeta); for i = 1:length(metaFields) theField = metaFields{i}; theFieldDef = userMeta.(theField); nRows = size(theFieldDef,1); nCols = size(theFieldDef,2); temp = []; if nRows>1 for ii = 1:nRows temp = [temp,' ',theFieldDef(ii,1:nCols)]; end theFieldDef = temp; end if ~strcmp(theField,'bins') && ... %don't write these attributes b/c ~strcmp(theField,'freqs') && ... %they are not read from the .aqa files correctly ~strcmp(theField,'gains') %and their information is provided in other attributes cdfs.(theField) = theFieldDef; end end % write additional metadata cdfs.CREATION_DATE = ncchar(datestr(now)); cdfs.DESCRIPT = ncchar('Aquascat ABS raw data statistics file'); cdfs.DATA_TYPE = ncchar('ABS'); % define dimensions cdfs('burst') = 0; %unlimited cdfs('bin') = userMeta.nBins; cdfs('pctile') = userMeta.nPctiles; cdfs('xducer') = userMeta.nXducers; % define stats variables cdfs{'time'} = nclong('burst'); cdfs{'time'}.FORTRAN_format = ncchar('F10.2'); cdfs{'time'}.units = ncchar('True Julian Day'); cdfs{'time'}.type = ncchar('UNEVEN'); cdfs{'time'}.epic_code = nclong(624); cdfs{'time'}.FillValue_ = nclong(0); cdfs{'time2'} = nclong('burst') ; cdfs{'time2'}.FORTRAN_format = ncchar('F10.2'); cdfs{'time2'}.units = ncchar('msec since 0:00 GMT'); cdfs{'time2'}.type = ncchar('UNEVEN'); cdfs{'time2'}.epic_code = nclong(624); cdfs{'time2'}.FillValue_ = nclong(0); cdfs{'burst'} = nclong('burst'); cdfs{'burst'}.FORTRAN_format = ncchar('F10.2'); cdfs{'burst'}.units = ncchar('counts'); cdfs{'burst'}.type = ncchar('EVEN'); cdfs{'burst'}.FillValue_ = nclong(0); cdfs{'pctile'} = nclong('pctile'); cdfs{'pctile'}.FORTRAN_format = ncchar('F10.2'); cdfs{'pctile'}.units = ncchar('%'); cdfs{'pctile'}.type = ncchar('EVEN'); cdfs{'pctile'}.FillValue_ = nclong(0); cdfs{'lat'} = ncfloat('lat'); cdfs{'lat'}.FORTRAN_format = ncchar('F10.4'); cdfs{'lat'}.units = ncchar('degree_north'); cdfs{'lat'}.type = ncchar('EVEN'); cdfs{'lat'}.epic_code = nclong(500); cdfs{'lon'} = ncfloat('lon'); cdfs{'lon'}.FORTRAN_format = ncchar('F10.4'); cdfs{'lon'}.units = ncchar('degree_east'); cdfs{'lon'}.type = ncchar('EVEN'); cdfs{'lon'}.epic_code = nclong(502); cdfs{'r'} = ncfloat('bin','xducer'); cdfs{'r'}.long_name = ncchar('Distance from ABS sensor head (m)'); cdfs{'r'}.units = ncchar('m'); cdfs{'r'}.valid_range = ncfloat([0 5000]); cdfs{'r'}.sensor_type = cdfs.INST_TYPE(:); cdfs{'r'}.height = ncchar([num2str(cdfs.sensor_height(:)),' m']); cdfs{'r'}.serial = ncchar(cdfs.serial_number(:)); cdfs{'r'}.FORTRAN_format = ncchar('F10.2'); cdfs{'r'}.FillValue_ = ncfloat(1.00000004091848e+035); cdfs{'abs_trans1_mean'} = ncfloat('burst','bin'); cdfs{'abs_trans1_mean'}.long_name = ncchar(['Mean Amplitude at ',num2str(cdfs.frequency1(:)),' Mhz']); cdfs{'abs_trans1_mean'}.units = ncchar('ABS units'); cdfs{'abs_trans1_mean'}.valid_range = ncfloat([0 1e16]); cdfs{'abs_trans1_mean'}.sensor_type = cdfs.INST_TYPE(:); cdfs{'abs_trans1_mean'}.height = ncchar([num2str(cdfs.sensor_height(:)),' m']); cdfs{'abs_trans1_mean'}.serial = ncchar(cdfs.serial_number(:)); cdfs{'abs_trans1_mean'}.frequency = ncchar([num2str(cdfs.frequency1(:)),' Mhz']); cdfs{'abs_trans1_mean'}.FORTRAN_format = ncchar('F10.2'); cdfs{'abs_trans1_mean'}.epic_code = 1900; cdfs{'abs_trans1_mean'}.FillValue_ = ncfloat(1.00000004091848e+035); cdfs{'abs_trans2_mean'} = ncfloat('burst','bin'); cdfs{'abs_trans2_mean'}.long_name = ncchar(['Mean Amplitude at ',num2str(cdfs.frequency2(:)),' Mhz']); cdfs{'abs_trans2_mean'}.units = ncchar('ABS units'); cdfs{'abs_trans2_mean'}.valid_range = ncfloat([0 1e16]); cdfs{'abs_trans2_mean'}.sensor_type = cdfs.INST_TYPE(:); cdfs{'abs_trans2_mean'}.height = ncchar([num2str(cdfs.sensor_height(:)),' m']); cdfs{'abs_trans2_mean'}.serial = ncchar(cdfs.serial_number(:)); cdfs{'abs_trans2_mean'}.frequency = ncchar([num2str(cdfs.frequency2(:)),' Mhz']); cdfs{'abs_trans2_mean'}.FORTRAN_format = ncchar('F10.2'); cdfs{'abs_trans2_mean'}.epic_code = 1900; cdfs{'abs_trans2_mean'}.FillValue_ = ncfloat(1.00000004091848e+035); cdfs{'abs_trans3_mean'} = ncfloat('burst','bin'); cdfs{'abs_trans3_mean'}.long_name = ncchar(['Mean Amplitude at ',num2str(cdfs.frequency3(:)),' Mhz']); cdfs{'abs_trans3_mean'}.units = ncchar('ABS units'); cdfs{'abs_trans3_mean'}.valid_range = ncfloat([0 1e16]); cdfs{'abs_trans3_mean'}.sensor_type = cdfs.INST_TYPE(:); cdfs{'abs_trans3_mean'}.height = ncchar([num2str(cdfs.sensor_height(:)),' m']); cdfs{'abs_trans3_mean'}.serial = ncchar(cdfs.serial_number(:)); cdfs{'abs_trans3_mean'}.frequency = ncchar([num2str(cdfs.frequency3(:)),' Mhz']); cdfs{'abs_trans3_mean'}.FORTRAN_format = ncchar('F10.2'); cdfs{'abs_trans3_mean'}.epic_code = 1900; cdfs{'abs_trans3_mean'}.FillValue_ = ncfloat(1.00000004091848e+035); cdfs{'abs_trans1_mean_sq'} = ncfloat('burst','bin'); cdfs{'abs_trans1_mean_sq'}.long_name = ncchar(['Squared Mean Amplitude at ',num2str(cdfs.frequency1(:)),' Mhz']); cdfs{'abs_trans1_mean_sq'}.units = ncchar('ABS units^2'); cdfs{'abs_trans1_mean_sq'}.valid_range = ncfloat([0 1e16]); cdfs{'abs_trans1_mean_sq'}.sensor_type = cdfs.INST_TYPE(:); cdfs{'abs_trans1_mean_sq'}.height = ncchar([num2str(cdfs.sensor_height(:)),' m']); cdfs{'abs_trans1_mean_sq'}.serial = ncchar(cdfs.serial_number(:)); cdfs{'abs_trans1_mean_sq'}.frequency = ncchar([num2str(cdfs.frequency1(:)),' Mhz']); cdfs{'abs_trans1_mean_sq'}.FORTRAN_format = ncchar('F10.2'); cdfs{'abs_trans1_mean_sq'}.epic_code = 1901; cdfs{'abs_trans1_mean_sq'}.FillValue_ = ncfloat(1.00000004091848e+035); cdfs{'abs_trans2_mean_sq'} = ncfloat('burst','bin'); cdfs{'abs_trans2_mean_sq'}.long_name = ncchar(['Squared Mean Amplitude at ',num2str(cdfs.frequency2(:)),' Mhz']); cdfs{'abs_trans2_mean_sq'}.units = ncchar('ABS units^2'); cdfs{'abs_trans2_mean_sq'}.valid_range = ncfloat([0 1e16]); cdfs{'abs_trans2_mean_sq'}.sensor_type = cdfs.INST_TYPE(:); cdfs{'abs_trans2_mean_sq'}.height = ncchar([num2str(cdfs.sensor_height(:)),' m']); cdfs{'abs_trans2_mean_sq'}.serial = ncchar(cdfs.serial_number(:)); cdfs{'abs_trans2_mean_sq'}.frequency = ncchar([num2str(cdfs.frequency2(:)),' Mhz']); cdfs{'abs_trans2_mean_sq'}.FORTRAN_format = ncchar('F10.2'); cdfs{'abs_trans2_mean_sq'}.epic_code = 1901; cdfs{'abs_trans2_mean_sq'}.FillValue_ = ncfloat(1.00000004091848e+035); cdfs{'abs_trans3_mean_sq'} = ncfloat('burst','bin'); cdfs{'abs_trans3_mean_sq'}.long_name = ncchar(['Squared Mean Amplitude at ',num2str(cdfs.frequency3(:)),' Mhz']); cdfs{'abs_trans3_mean_sq'}.units = ncchar('ABS units^2'); cdfs{'abs_trans3_mean_sq'}.valid_range = ncfloat([0 1e16]); cdfs{'abs_trans3_mean_sq'}.sensor_type = cdfs.INST_TYPE(:); cdfs{'abs_trans3_mean_sq'}.height = ncchar([num2str(cdfs.sensor_height(:)),' m']); cdfs{'abs_trans3_mean_sq'}.serial = ncchar(cdfs.serial_number(:)); cdfs{'abs_trans3_mean_sq'}.frequency = ncchar([num2str(cdfs.frequency3(:)),' Mhz']); cdfs{'abs_trans3_mean_sq'}.FORTRAN_format = ncchar('F10.2'); cdfs{'abs_trans3_mean_sq'}.epic_code = 1901; cdfs{'abs_trans3_mean_sq'}.FillValue_ = ncfloat(1.00000004091848e+035); cdfs{'abs_trans1_std'} = ncfloat('burst','bin'); cdfs{'abs_trans1_std'}.long_name = ncchar(['Amplitude Standard Deviation at ',num2str(cdfs.frequency1(:)),' Mhz']); cdfs{'abs_trans1_std'}.units = ncchar('ABS units'); cdfs{'abs_trans1_std'}.valid_range = ncfloat([0 1e16]); cdfs{'abs_trans1_std'}.sensor_type = cdfs.INST_TYPE(:); cdfs{'abs_trans1_std'}.height = ncchar([num2str(cdfs.sensor_height(:)),' m']); cdfs{'abs_trans1_std'}.serial = ncchar(cdfs.serial_number(:)); cdfs{'abs_trans1_std'}.frequency = ncchar([num2str(cdfs.frequency3(:)),' Mhz']); cdfs{'abs_trans1_std'}.FORTRAN_format = ncchar('F10.2'); cdfs{'abs_trans1_std'}.epic_code = 1902; cdfs{'abs_trans1_std'}.FillValue_ = ncfloat(1.00000004091848e+035); cdfs{'abs_trans2_std'} = ncfloat('burst','bin'); cdfs{'abs_trans2_std'}.long_name = ncchar(['Amplitude Standard Deviation at ',num2str(cdfs.frequency2(:)),' Mhz']); cdfs{'abs_trans2_std'}.units = ncchar('ABS units'); cdfs{'abs_trans2_std'}.valid_range = ncfloat([0 1e16]); cdfs{'abs_trans2_std'}.sensor_type = cdfs.INST_TYPE(:); cdfs{'abs_trans2_std'}.height = ncchar([num2str(cdfs.sensor_height(:)),' m']); cdfs{'abs_trans2_std'}.serial = ncchar(cdfs.serial_number(:)); cdfs{'abs_trans2_std'}.frequency = ncchar([num2str(cdfs.frequency3(:)),' Mhz']); cdfs{'abs_trans2_std'}.FORTRAN_format = ncchar('F10.2'); cdfs{'abs_trans2_std'}.epic_code = 1902; cdfs{'abs_trans2_std'}.FillValue_ = ncfloat(1.00000004091848e+035); cdfs{'abs_trans3_std'} = ncfloat('burst','bin'); cdfs{'abs_trans3_std'}.long_name = ncchar(['Amplitude Standard Deviation at ',num2str(cdfs.frequency3(:)),' Mhz']); cdfs{'abs_trans3_std'}.units = ncchar('ABS units'); cdfs{'abs_trans3_std'}.valid_range = ncfloat([0 1e16]); cdfs{'abs_trans3_std'}.sensor_type = cdfs.INST_TYPE(:); cdfs{'abs_trans3_std'}.height = ncchar([num2str(cdfs.sensor_height(:)),' m']); cdfs{'abs_trans3_std'}.serial = ncchar(cdfs.serial_number(:)); cdfs{'abs_trans3_std'}.frequency = ncchar([num2str(cdfs.frequency3(:)),' Mhz']); cdfs{'abs_trans3_std'}.FORTRAN_format = ncchar('F10.2'); cdfs{'abs_trans3_std'}.epic_code = 1902; cdfs{'abs_trans3_std'}.FillValue_ = ncfloat(1.00000004091848e+035); cdfs{'abs_trans1_std_sq'} = ncfloat('burst','bin'); cdfs{'abs_trans1_std_sq'}.long_name = ncchar(['Squared Amplitude Standard Deviation at ',num2str(cdfs.frequency1(:)),' Mhz']); cdfs{'abs_trans1_std_sq'}.units = ncchar('ABS units^2'); cdfs{'abs_trans1_std_sq'}.valid_range = ncfloat([0 1e16]); cdfs{'abs_trans1_std_sq'}.sensor_type = cdfs.INST_TYPE(:); cdfs{'abs_trans1_std_sq'}.height = ncchar([num2str(cdfs.sensor_height(:)),' m']); cdfs{'abs_trans1_std_sq'}.serial = ncchar(cdfs.serial_number(:)); cdfs{'abs_trans1_std_sq'}.frequency = ncchar([num2str(cdfs.frequency3(:)),' Mhz']); cdfs{'abs_trans1_std_sq'}.FORTRAN_format = ncchar('F10.2'); cdfs{'abs_trans1_std_sq'}.epic_code = 1903; cdfs{'abs_trans1_std_sq'}.FillValue_ = ncfloat(1.00000004091848e+035); cdfs{'abs_trans2_std_sq'} = ncfloat('burst','bin'); cdfs{'abs_trans2_std_sq'}.long_name = ncchar(['Squared Amplitude Standard Deviation at ',num2str(cdfs.frequency2(:)),' Mhz']); cdfs{'abs_trans2_std_sq'}.units = ncchar('ABS units^2'); cdfs{'abs_trans2_std_sq'}.valid_range = ncfloat([0 1e16]); cdfs{'abs_trans2_std_sq'}.sensor_type = cdfs.INST_TYPE(:); cdfs{'abs_trans2_std_sq'}.height = ncchar([num2str(cdfs.sensor_height(:)),' m']); cdfs{'abs_trans2_std_sq'}.serial = ncchar(cdfs.serial_number(:)); cdfs{'abs_trans2_std_sq'}.frequency = ncchar([num2str(cdfs.frequency3(:)),' Mhz']); cdfs{'abs_trans2_std_sq'}.FORTRAN_format = ncchar('F10.2'); cdfs{'abs_trans2_std_sq'}.epic_code = 1903; cdfs{'abs_trans2_std_sq'}.FillValue_ = ncfloat(1.00000004091848e+035); cdfs{'abs_trans3_std_sq'} = ncfloat('burst','bin'); cdfs{'abs_trans3_std_sq'}.long_name = ncchar(['Squared Amplitude Standard Deviation at ',num2str(cdfs.frequency3(:)),' Mhz']); cdfs{'abs_trans3_std_sq'}.units = ncchar('ABS units^2'); cdfs{'abs_trans3_std_sq'}.valid_range = ncfloat([0 1e16]); cdfs{'abs_trans3_std_sq'}.sensor_type = cdfs.INST_TYPE(:); cdfs{'abs_trans3_std_sq'}.height = ncchar([num2str(cdfs.sensor_height(:)),' m']); cdfs{'abs_trans3_std_sq'}.serial = ncchar(cdfs.serial_number(:)); cdfs{'abs_trans3_std_sq'}.frequency = ncchar([num2str(cdfs.frequency3(:)),' Mhz']); cdfs{'abs_trans3_std_sq'}.FORTRAN_format = ncchar('F10.2'); cdfs{'abs_trans3_std_sq'}.epic_code = 1903; cdfs{'abs_trans3_std_sq'}.FillValue_ = ncfloat(1.00000004091848e+035); cdfs{'abs_trans1_pctl'} = ncfloat('burst','bin','pctile'); cdfs{'abs_trans1_pctl'}.long_name = ncchar(['Amplitude Percentiles at ',num2str(cdfs.frequency1(:)),' Mhz']); cdfs{'abs_trans1_pctl'}.units = ncchar('ABS units'); cdfs{'abs_trans1_pctl'}.valid_range = ncfloat([0 1e16]); cdfs{'abs_trans1_pctl'}.sensor_type = cdfs.INST_TYPE(:); cdfs{'abs_trans1_pctl'}.height = ncchar([num2str(cdfs.sensor_height(:)),' m']); cdfs{'abs_trans1_pctl'}.serial = ncchar(cdfs.serial_number(:)); cdfs{'abs_trans1_pctl'}.frequency = ncchar([num2str(cdfs.frequency1(:)),' Mhz']); cdfs{'abs_trans1_pctl'}.FORTRAN_format = ncchar('F10.2'); cdfs{'abs_trans1_pctl'}.epic_code = 1904; cdfs{'abs_trans1_pctl'}.FillValue_ = ncfloat(1.00000004091848e+035); cdfs{'abs_trans1_pctl_sq'} = ncfloat('burst','bin','pctile'); cdfs{'abs_trans1_pctl_sq'}.long_name = ncchar(['Squared Amplitude Percentiles at ',num2str(cdfs.frequency1(:)),' Mhz']); cdfs{'abs_trans1_pctl_sq'}.units = ncchar('ABS units^2'); cdfs{'abs_trans1_pctl_sq'}.valid_range = ncfloat([0 1e16]); cdfs{'abs_trans1_pctl_sq'}.sensor_type = cdfs.INST_TYPE(:); cdfs{'abs_trans1_pctl_sq'}.height = ncchar([num2str(cdfs.sensor_height(:)),' m']); cdfs{'abs_trans1_pctl_sq'}.serial = ncchar(cdfs.serial_number(:)); cdfs{'abs_trans1_pctl_sq'}.frequency = ncchar([num2str(cdfs.frequency1(:)),' Mhz']); cdfs{'abs_trans1_pctl_sq'}.FORTRAN_format = ncchar('F10.2'); cdfs{'abs_trans1_pctl_sq'}.epic_code = 1905; cdfs{'abs_trans1_pctl_sq'}.FillValue_ = ncfloat(1.00000004091848e+035); cdfs{'abs_trans2_pctl'} = ncfloat('burst','bin','pctile'); cdfs{'abs_trans2_pctl'}.long_name = ncchar(['Amplitude Percentiles at ',num2str(cdfs.frequency2(:)),' Mhz']); cdfs{'abs_trans2_pctl'}.units = ncchar('ABS units'); cdfs{'abs_trans2_pctl'}.valid_range = ncfloat([0 1e16]); cdfs{'abs_trans2_pctl'}.sensor_type = cdfs.INST_TYPE(:); cdfs{'abs_trans2_pctl'}.height = ncchar([num2str(cdfs.sensor_height(:)),' m']); cdfs{'abs_trans2_pctl'}.serial = ncchar(cdfs.serial_number(:)); cdfs{'abs_trans2_pctl'}.frequency = ncchar([num2str(cdfs.frequency2(:)),' Mhz']); cdfs{'abs_trans2_pctl'}.FORTRAN_format = ncchar('F10.2'); cdfs{'abs_trans2_pctl'}.epic_code = 1904; cdfs{'abs_trans2_pctl'}.FillValue_ = ncfloat(1.00000004091848e+035); cdfs{'abs_trans2_pctl_sq'} = ncfloat('burst','bin','pctile'); cdfs{'abs_trans2_pctl_sq'}.long_name = ncchar(['Squared Amplitude Percentiles at ',num2str(cdfs.frequency2(:)),' Mhz']); cdfs{'abs_trans2_pctl_sq'}.units = ncchar('ABS units^2'); cdfs{'abs_trans2_pctl_sq'}.valid_range = ncfloat([0 1e16]); cdfs{'abs_trans2_pctl_sq'}.sensor_type = cdfs.INST_TYPE(:); cdfs{'abs_trans2_pctl_sq'}.height = ncchar([num2str(cdfs.sensor_height(:)),' m']); cdfs{'abs_trans2_pctl_sq'}.serial = ncchar(cdfs.serial_number(:)); cdfs{'abs_trans2_pctl_sq'}.frequency = ncchar([num2str(cdfs.frequency2(:)),' Mhz']); cdfs{'abs_trans2_pctl_sq'}.FORTRAN_format = ncchar('F10.2'); cdfs{'abs_trans2_pctl_sq'}.epic_code = 1905; cdfs{'abs_trans2_pctl_sq'}.FillValue_ = ncfloat(1.00000004091848e+035); cdfs{'abs_trans3_pctl'} = ncfloat('burst','bin','pctile'); cdfs{'abs_trans3_pctl'}.long_name = ncchar(['Amplitude Percentiles at ',num2str(cdfs.frequency3(:)),' Mhz']); cdfs{'abs_trans3_pctl'}.units = ncchar('ABS units'); cdfs{'abs_trans3_pctl'}.valid_range = ncfloat([0 1e16]); cdfs{'abs_trans3_pctl'}.sensor_type = cdfs.INST_TYPE(:); cdfs{'abs_trans3_pctl'}.height = ncchar([num2str(cdfs.sensor_height(:)),' m']); cdfs{'abs_trans3_pctl'}.serial = ncchar(cdfs.serial_number(:)); cdfs{'abs_trans3_pctl'}.frequency = ncchar([num2str(cdfs.frequency3(:)),' Mhz']); cdfs{'abs_trans3_pctl'}.FORTRAN_format = ncchar('F10.2'); cdfs{'abs_trans3_pctl'}.epic_code = 1904; cdfs{'abs_trans3_pctl'}.FillValue_ = ncfloat(1.00000004091848e+035); cdfs{'abs_trans3_pctl_sq'} = ncfloat('burst','bin','pctile'); cdfs{'abs_trans3_pctl_sq'}.long_name = ncchar(['Squared Amplitude Percentiles at ',num2str(cdfs.frequency3(:)),' Mhz']); cdfs{'abs_trans3_pctl_sq'}.units = ncchar('ABS units^2'); cdfs{'abs_trans3_pctl_sq'}.valid_range = ncfloat([0 1e16]); cdfs{'abs_trans3_pctl_sq'}.sensor_type = cdfs.INST_TYPE(:); cdfs{'abs_trans3_pctl_sq'}.height = ncchar([num2str(cdfs.sensor_height(:)),' m']); cdfs{'abs_trans3_pctl_sq'}.serial = ncchar(cdfs.serial_number(:)); cdfs{'abs_trans3_pctl_sq'}.frequency = ncchar([num2str(cdfs.frequency3(:)),' Mhz']); cdfs{'abs_trans3_pctl_sq'}.FORTRAN_format = ncchar('F10.2'); cdfs{'abs_trans3_pctl_sq'}.epic_code = 1905; cdfs{'abs_trans3_pctl_sq'}.FillValue_ = ncfloat(1.00000004091848e+035); endef(cdfs) return % ---------------------- Subfunction ------------------------------------ % function calc_minmax_vals(cdf) theVars = var(cdf); for i = 1:length(theVars), if ~strcmp(ncnames(theVars{i}),'time') && ... ~strcmp(ncnames(theVars{i}),'time2') data = theVars{i}(:); N = ndims(data); if N==1 %1D data theVars{i}.minimum = ncfloat(min(data)); theVars{i}.maximum = ncfloat(max(data)); elseif N==2 %2D data [row, col] = size(data); mins = ones(1,col); maxs = ones(1,col); for icol = 1:col mins(icol) = min(data(:,icol)); maxs(icol) = max(data(:,icol)); end theVars{i}.minimum = ncfloat(mins); theVars{i}.maximum = ncfloat(maxs); clear mins maxs elseif N==3 %3D data [row, col, lvl] = size(data); for jlvl = 1:lvl mins(:,jlvl) = min(data(:,:,jlvl))'; maxs(:,jlvl) = max(data(:,:,jlvl))'; end theVars{i}.minimum = ncfloat(mins); theVars{i}.maximum = ncfloat(maxs); clear mins maxs end clear data end end return