function trimprofile(inFile,bins2keep,trimFile) % function trimprofile(inFile,trimFile,bins2keep) % or % function trimprofile(settings) % where % settings.inFile = the cdf input file to trim % settings.trimFile = the cdf trimmed output file % if not provided, file will be written appended with 'T' % settings.bins2keep = [M N] for M:N bins to preserve % may also be uncontiguous indeces [ 1 3 5 9 11]; % keeping only two bins? then use % settings.bins2keep.bin1 % settings.bins2keep.bin2 % % this code expects EPIC convention files where trimming is done % based on the 'depth' dimension % this code expects depth to be the first or second dimension in a variable %%% START USGS BOILERPLATE -------------% % Use of this program is described in: % % Acoustic Doppler Current Profiler Data Processing System Manual % Jessica M. Côté, Frances A. Hotchkiss, Marinna Martini, Charles R. Denham % Revisions by: Andrée L. Ramsey, Stephen Ruane % U.S. Geological Survey Open File Report 00-458 % Check for later versions of this Open-File, it is a living document. % % Program written in Matlab v7.1.0 SP3 % Program updated in Matlab 7.2.0.232 (R2006a) % 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." % %%% END USGS BOILERPLATE -------------- % written by Marinna Martini 27 Jun 08 % get the current SVN version- the value is automatically obtained in svn % is the file's svn.keywords which is set to "Revision" rev_info = 'SVN $Revision: $'; disp(sprintf('%s %s running',mfilename,rev_info)) if nargin==1 && isstruct(inFile), settings = inFile; if isfield(settings,'inFile'), inFile = settings.inFile; else inFile = ''; end if isfield(settings,'trimFile'), trimFile = settings.trimFile; else trimFile = ''; end if isfield(settings,'bins2keep'), bins2keep = settings.bins2keep; else bins2keep = []; end end if isempty(inFile) [theFile, thePath] = uigetfile('*.cdf', 'Select ABSS netcdf File to trim:'); if isempty(inFile), return, end inFile = fullfile(thePath, theFile); end % make sure it's EPIC, or some other thing we expect cdfin = netcdf(inFile); if isempty(cdfin), disp(sprintf('unable to open %s',inFile)) return end % TODO check for EPIC convention dimnames = ncnames(dim(cdfin)); dimflag = 0; for idim = 1:length(dimnames), if strcmp(dimnames(idim),'depth'), dimflag = 1; end end if dimflag, if length(dim(cdfin,'depth')) == 1, disp('There is only one depth bin in this data, there is nothing to trim') close(cdfin); return end else disp('Depth dimension required for this m-file to work') close(cdfin); return end if isempty(trimFile) [thePath, theFile, theExt] = fileparts(inFile); trimFile = fullfile(thePath, [theFile,'T',theExt]); end if isstruct(bins2keep), bins2keep = [bins2keep.bin1 bins2keep.bin2]; elseif length(bins2keep) == 2, bins2keep = bins2keep(1):bins2keep(2); end depths = cdfin{'depth'}(:); disp(sprintf('Original depths from %d at %f m to %d at %f m',... 1,depths(1),length(depths),depths(end))) if find(bins2keep < 0), disp('some bins to keep are < zero, aborting') close(cdfin); return end if find(bins2keep > length(depths)), disp(sprintf('Some bins to keep are > the number of bins (%d), aborting',... length(depths))) close(cdfin); return end newdepths = depths(bins2keep); disp(sprintf('Keeping bins %d to %d',bins2keep(1),bins2keep(end))) disp(sprintf('From depths, bin index, or cell %g to %g',... newdepths(1),depths(end))) disp(sprintf('Copying %s to %s',inFile,trimFile)); copyfile(inFile,trimFile); % find the depth dependent variables theVar = ncnames(var(cdfin)); % variable names v2trim = zeros(size(theVar)); % flags for ivar = 1:length(theVar), %disp(theVar{ivar}) theDim = ncnames(dim(cdfin{theVar{ivar}})); for idim = 1:length(theDim), %disp(theDim{idim}) if strcmp(theDim{idim},'depth'), disp(sprintf('%s has a depth dimension and will be trimmed',theVar{ivar})); v2trim(ivar) = 1; end end end % open the new file cdfT=netcdf(trimFile,'clobber'); if isempty(cdfT), return, end; % Duplication of NetCDF objects via "copy": % copy(f, myNetCDF) copies netcdf f into myNetCDF. % copy(d, f) copies dimension d into netcdf f. % copy(a, f) copies attribute a into netcdf f. % copy(a, v) copies attribute a into variable v. % copy(v, f, copyData, copyAttributes) copies variable v into % netcdf f, as directed by the flags (defaults = 0). % copy(v, myVariable, copyData, copyAttributes) copies the % contents of variable v into variable myVariable, as % directed by the flags (defaults = 0). % copy global attributes gattobj = att(cdfin); for iatt = 1: length(gattobj), copy(gattobj(iatt), cdfT); end % copy dimensions dimobj = dim(cdfin); theDim = ncnames(dim(cdfin)); for idim = 1:length(theDim), if strcmp(theDim(idim),'depth'), disp(sprintf('Found depth, defining new dimension to length %d',... length(newdepths))) cdfT('depth') = length(newdepths); else copy(dimobj(idim), cdfT); end end depidx = 0; latidx = 0; lonidx = 0; timidx = 0; odimidx = 0; iodim = 0; tic; burstflag = 0; % copy the data, resized appropriately, this is not pretty! for ivar = 1:length(theVar), burstdim = 0; disp(sprintf('copying %s',theVar{ivar})) if v2trim(ivar), copy(cdfin{theVar{ivar}},cdfT,0,1) % copy attributes only % check the chapes of things by checking the first dimension % this assumes EPIC conventionality theDim = ncnames(dim(cdfin{theVar{ivar}})); ndims = length(theDim); % now, where is depth and time and are there an extra dimensions for idim = 1:ndims, switch theDim{idim}, case 'depth', depidx = idim; % could be || profile || bin || cell case 'lat', latidx = idim; case 'lon', lonidx = idim; case 'time', timidx = idim; % could be || burst || ens otherwise, iodim = iodim + 1; % this might be sample, odimidx(iodim) = idim; end if strcmp(theDim{idim},'profile') || strcmp(theDim{idim},'sample'), disp('variable contains burst data') burstdim = idim; burstflag = 1; end end switch ndims, case 1, % probably depth as the ordinate dimension cdfT{theVar{ivar}}(:) = cdfin{theVar{ivar}}(bins2keep); case 2, % probably time and depth, though this would be unusual if depidx == 1, cdfT{theVar{ivar}}(:,:) = cdfin{theVar{ivar}}(bins2keep,:); elseif depidx == 2, cdfT{theVar{ivar}}(:,:) = cdfin{theVar{ivar}}(:,bins2keep); end case 3, % probably time, depth and something else but not lat & lon if ~burstdim, % who knows... if depidx == 1, cdfT{theVar{ivar}}(:,:,:) = cdfin{theVar{ivar}}(bins2keep,:,:); elseif depidx == 2, cdfT{theVar{ivar}}(:,:,:) = cdfin{theVar{ivar}}(:,bins2keep,:); elseif depidx == 3, cdfT{theVar{ivar}}(:,:,:) = cdfin{theVar{ivar}}(:,:,bins2keep); end else % this is burst, and must take it in chunks so as not to run out of memory nprofiles = length(cdfin(theDim{burstdim})); for iprofile = 1:nprofiles, if depidx == 1, if burstdim == 2, cdfT{theVar{ivar}}(:,iprofile,:) = cdfin{theVar{ivar}}(bins2keep,iprofile,:); else cdfT{theVar{ivar}}(:,:,iprofile) = cdfin{theVar{ivar}}(bins2keep,:,iprofile); end elseif depidx == 2, if burstdim == 1, % unlikely, but while I'm at it might as well... cdfT{theVar{ivar}}(iprofile,:,:) = cdfin{theVar{ivar}}(iprofile,bins2keep,:); else cdfT{theVar{ivar}}(:,:,iprofile) = cdfin{theVar{ivar}}(:,bins2keep,iprofile); end elseif depidx == 3, if burstdim == 1, % unlikely, but while I'm at it might as well... cdfT{theVar{ivar}}(iprofile,:,:) = cdfin{theVar{ivar}}(iprofile,:,bins2keep); else cdfT{theVar{ivar}}(:,iprofile,:) = cdfin{theVar{ivar}}(:,iprofile,bins2keep); end end %Update the user with the code's progress if mod(iprofile,100)==0 fprintf('Finished writing profile %d of %d; %6.2f minutes elapsed\n',iprofile,nprofiles,toc/60) end end end case 4, % probably time, depth, lat, lon if depidx == 1, cdfT{theVar{ivar}}(:,:,:,:) = cdfin{theVar{ivar}}(bins2keep,:,:,:); elseif depidx == 2, cdfT{theVar{ivar}}(:,:,:,:) = cdfin{theVar{ivar}}(:,bins2keep,:,:); elseif depidx == 3, cdfT{theVar{ivar}}(:,:,:,:) = cdfin{theVar{ivar}}(:,:,bins2keep,:); elseif depidx == 4, cdfT{theVar{ivar}}(:,:,:,:) = cdfin{theVar{ivar}}(:,:,:,bins2keep); end case 5, % probably time, depth, lat, lon and something else if depidx == 1, cdfT{theVar{ivar}}(:,:,:,:,:) = cdfin{theVar{ivar}}(bins2keep,:,:,:,:); elseif depidx == 2, cdfT{theVar{ivar}}(:,:,:,:,:) = cdfin{theVar{ivar}}(:,bins2keep,:,:,:); elseif depidx == 3, cdfT{theVar{ivar}}(:,:,:,:,:) = cdfin{theVar{ivar}}(:,:,bins2keep,:,:); elseif depidx == 4, cdfT{theVar{ivar}}(:,:,:,:,:) = cdfin{theVar{ivar}}(:,:,:,bins2keep,:); elseif depidx == 5, cdfT{theVar{ivar}}(:,:,:,:,:) = cdfin{theVar{ivar}}(:,:,:,:,bins2keep); end otherwise, disp('This variable has depth with more than 5 dimensions, you will have to modify the code') end else copy(cdfin{theVar{ivar}},cdfT,1,1) % copy all, no trimming end end % disp(sprintf('Data is from bin 1 at %7.2f to last bin at %7.2f meters',... % cdf{'depth'}(1),cdf{'depth'}(end))) % % % add minimums and maximums % TODO - this currently bombs due to outo f memry on burst files. if ~burstflag, add_minmaxvalues(cdfT); end close(cdfin) close(cdfT) %Done % hist = cdf.history(:); % cdf.history = sprintf('Bins trimmed by %s %s;\n%s',... % mfilename,rev_info,hist);