getbtrack.m
author A.M. Thurnherr <athurnherr@yahoo.com>
Mon, 23 Feb 2015 09:19:46 +0000
changeset 15 3746197831db
parent 0 0a450563f904
child 22 624b1ed6e9c9
permissions -rw-r--r--
IX11beta for CLIVAR P16

function [d,p]=getbtrack(d,p);
% function [d,p]=getbtrack(d,p);
%
% create own bottom track in addition to the one used before
%

% force own distance to RDI bottom track
p=setdefv(p,'bottomdist',0);
% "manual" bottom track for down looker
p=setdefv(p,'btrk_mode',3);
% p.btrk_ts is in dB to detect bottom above bin1 level (for own btm track)
p=setdefv(p,'btrk_ts',10);
% p.btrk_below gives bin used below target strength maximum
p=setdefv(p,'btrk_below',0.5);
% p.btrk_range gives range of allowed bottom track ranges
p=setdefv(p,'btrk_range',[300 50]);
% maximum allowed difference between reference layer W and W bottom track
p=setdefv(p,'btrk_wlim',0.05);

p=setdefv(p,'btrk_used',0);

disp('GETBTRACK creates own bottom track in addition to RDI')

% convert echo amplitude to relative target strength
% at=0.039; % attenuation dB/m for 150 kHz
% at=0.062; % attenuation dB/m for 300 kHz
if d.down.Frequency==300,
  p=setdefv(p,'ts_att_dn',0.06);
else
  p=setdefv(p,'ts_att_dn',0.039);
end
d.tg(d.izd,:)=targ(d.ts(d.izd,:),d.zd,p.ts_att_dn);

if length(d.izu)>0
 if d.up.Frequency==300,
  p=setdefv(p,'ts_att_up',0.06);
 else
  p=setdefv(p,'ts_att_up',0.039);
 end
 d.tg(d.izu,:)=targ(d.ts(d.izu,:),d.zu,p.ts_att_up);
end

% save bin number where down looker starts
ib1=d.izd(1)-1;
nbin=length(d.izd);

disp(['  in: p.btrk_mode ',int2str(p.btrk_mode),' and p.btrk_used ',int2str(p.btrk_used)])

if p.btrk_mode>=1
    if p.btrk_ts>0

      disp(' using increased bottom echo amplitudes to create bottom track')
      % don't use first bin
      fitb1=1;
      zd=d.zd(fitb1:end);
      ead=d.tg(d.izd(fitb1:end),:);
      % fit parabola to locate bottom
      [zmead,mead,imead]=localmax2(zd',ead);
      imead=imead+fitb1-1;
      dts=mead-ead(1,:);

      % decide which bin to use for bottom velocities
      dz=abs(diff(d.zd(1:2)));
      % imeadbv=round(imead+p.btrk_below);
      imeadbv=round((zmead-d.zd(1))/dz+1+p.btrk_below);

      if p.btrk_used==1
       if p.bottomdist==0
        % check RDI bottom track only if non zero
        ii=find(d.hbot<min(p.btrk_range));
        if length(ii)>0
         disp([' found ',int2str(length(ii)),' bottom depth below btrk_range ',...
            int2str(min(p.btrk_range))])
         d.bvel(ii,:)=nan;
         d.hbot(ii)=nan;
        end
        ii=find(d.hbot>max(p.btrk_range));
        if length(ii)>0
         disp([' found ',int2str(length(ii)),' bottom depth above btrk_range ',...
            int2str(max(p.btrk_range))])
         d.bvel(ii,:)=nan;
         d.hbot(ii)=nan;
        end
       end
       % save RDI bottom track
       d.bvel_rdi=d.bvel;
       d.hbot_rdi=d.hbot;
       ii=find(isfinite(d.bvel(:,1)+d.bvel(:,2)));
       if length(ii)<10, 
        disp(' found less than 10 RDI bottom track values, try own')
        p.btrk_used=0; 
       end
      end

      disp([' use ',num2str(p.btrk_below),...
         ' bins below maximum target strength for own bottom track velocity'])
      % locate acceptable bottom tracks (don't accept first/last bin)
      ii=find(dts>p.btrk_ts & ...
              zmead>min(p.btrk_range) & zmead<max(p.btrk_range) & ...
               imeadbv<(nbin-1) & imeadbv>fitb1);
 
      if length(ii)>0

      % save bottom distance data
       d.hbot_own=d.hbot+NaN;
       d.hbot_own(ii)=zmead(ii);

      % force bottom distance if RDI mode fails to report distance
       if p.bottomdist | p.btrk_mode==2 | p.btrk_used~=1
        d.hbot=d.hbot_own;
        disp([' created ',int2str(length(ii)),...
		' bottom distances'])
        if p.bottomdist, p.btrk_used = 12; end
       else
        disp([' created ',int2str(length(ii)),...
		' bottom distances keeping original'])
       end

       % make bottom velocity data
       bv=d.bvel+NaN;

       for j=1:length(ii)
          ji=ii(j);
          bv(ji,1)=medianan(d.ru(ib1+imeadbv(ji)+[-1,0,0,1],ji));
          bv(ji,2)=medianan(d.rv(ib1+imeadbv(ji)+[-1,0,0,1],ji));
          bv(ji,3)=medianan(d.rw(ib1+imeadbv(ji)+[-1,0,0,1],ji));
          bv(ji,4)=medianan(d.re(ib1+imeadbv(ji)+[-1,0,0,1],ji));
       end

       % check for W-bot 
       wref=medianan(d.rw(d.izd,:),2);
       ii=find(abs(wref'-bv(:,3))>p.btrk_wlim);
       disp([' removed ',int2str(length(ii)),...
           ' bottom track profiles W_btrk - W_ref difference > ',num2str(p.btrk_wlim)])
       bv(ii,:)=nan;

       % check for outlier
       bv=boutlier(bv,d.hbot_own,p);
       d.bvel_own=bv;
       ii=find(isfinite(bv(:,1)+bv(:,2)));

       if (p.btrk_used~=1 & p.btrk_used~=12) | p.btrk_mode==2
        p.btrk_used = 2;
        d.bvel=d.bvel_own;
        disp([' created ',int2str(length(ii)),...
		' bottom track data from normal velocities'])
       else
        disp([' created ',int2str(length(ii)),...
		' bottom track velocities keeping original'])
       end

      else
        if (p.btrk_used~=1 & p.btrk_used~=12)
         p.btrk_used = -1;
        end
        disp(' did not find any bottom echos to create own bottom track ')
      end
    else
      disp(' no valid own bottom track. Increase target strength difference ? ')
    end
else
 disp('force no bottom track data ')
 p.btrk_used = -1;
 d.bvel=d.bvel+nan;
 d.hbot=d.hbot+nan;
end
% summary output
disp([' out: p.btrk_mode ',int2str(p.btrk_mode),' and p.btrk_used ',int2str(p.btrk_used)])

%=================================
function [bvel,p] = boutlier(bvel,hbot,p);
% function [bvel,p] = boutlier(bvel,hbot,p);
%
%
% input  : bvel bottom track velocity
%           n       factor for outlier rejection
%                   n(1)*rms(data) first sweep
%                   n(2)*rms(data) second sweep etc.
%
% output :	d		changed LADCP analysis data structure
%
% version 0.1	last change 27.6.2000

n=p.outlier;
nblock=p.outlier_n;

dummyb = bvel*0;
if size(dummyb,2)~=4, disp(' no data '), return, end

si = size(dummyb);
sn = ceil(si(1)/nblock);


lob=length(find(isnan(dummyb)));

for i=1:length(n)
  for m=1:sn
    ind = (m-1)*nblock+[1:nblock];
    ii = find( ind<=si(1) );
    ind = ind(ii);
    % bottom track
     bvelt(ind,1)=bvel(ind,1)-medianan(bvel(ind,1));
     bu = find(abs(bvelt(ind,1))>n(i)*rms(bvelt(ind,1)));
     dummyb(ind(bu),:)=nan;
     bvelt(ind,2)=bvel(ind,2)-medianan(bvel(ind,2));
     bv = find(abs(bvelt(ind,2))>n(i)*rms(bvelt(ind,2)));
     dummyb(ind(bv),:)=nan;
     bw = find(abs(bvel(ind,3))>n(i)*rms(bvel(ind,3)));
     dummyb(ind(bw),:)=nan;
     hbot(ind)=hbot(ind)-medianan(hbot(ind));
     bh = find(abs(hbot(ind))>n(i)*rms(hbot(ind)));
     dummyb(ind(bh),:)=nan;
  end
  bvel = bvel + dummyb; 
  hbot = hbot + dummyb(:,1)'; 
end  
disp([' boutlier removed ',int2str(length(find(isnan(dummyb)))-lob),...
      ' bottom track velocities '])
return

%
function y = rms(x,dim)
%RMS    root-mean square. For vectors, RMS(x) returns the standard
%       deviation.  For matrices, RMS(X) is a row vector containing
%       the root-mean-square of each column. The difference to STD is
%       that here the mean is NOT removed.  
%       RMS(X,DIM) returns the root-mean-square of dimension DIM
%
%	See also STD,COV.
%

%       Uwe Send, IfM Kiel, Apr 1992
% added NaN handling   Gerd Krahmann, IfM Kiel, Oct 1993, Jun 1994
% removed bug in NaN handling   G.Krahmann, Aug 1994
% added compatibility to MATLAB 5	G.Krahmann, LODYC Paris, Jul 1997


  if nargin<2
    dim=min(find(size(x)>1));
  end

  if all(isnan(x))
    y=nan;
    return
  end    

  x = shiftdim(x,dim-1);
  s = size(x);
  so = s(1);
  s(1) = 1;

  for n = 1:prod(s)
    good = find(~isnan(x(:,n)));
    if ~isempty(good)
      y(1,n) = norm( x(good,n) ) / sqrt(length(good));
    else
      y(1,n) = NaN;
    end
  end
  y = reshape(y,s);
  y = shiftdim( y, ndims(x)-dim+1 );


%================================================
function [ts,bcs]=targ(ea,dis,at,bl,eas,ap)
% function [ts,bcs]=targ(ea,dis,at,bl,eas,ap)
% Target strength of EA for volume scatterer
% ea = echoamp in  dB
% dis = distance in  m
% at = attenuation dB/m
% bl = pulse/bin legth in  m
% eas = source level
% ap = aperature in degree
% M. Visbeck 2004

% make distance matrix if needed
[lr,lc]=size(ea);

if size(dis,2)==1 | size(dis,1)==1
 dis=dis(:);
 dis=repmat(dis,[1,lc]);
end

if nargin<3
 at=0.039; % attenuation dB/m for 150 kHz
 at=0.062; % attenuation dB/m for 300 kHz
end


%binlength
if nargin<4 , bl=median(abs(diff(dis(:,1)))); end

% source level in dB
if nargin <5, eas=100; end

% beam aperature in DEGREE convert to radian
if nargin <6, ap=2; end
al=ap*pi/180; 

% radius of top and bottom of each bin
r1=tan(al)*(dis-bl/2);
r2=tan(al)*(dis+bl/2);

% ensonified volume 
v=pi*bl/3*(r1.^2+r2.^2+r1.*r2);

% transmission loss
tl=20*log10(dis)+at*dis;

% target strength
ts=ea-eas+2*tl-10*log10(v);

if nargout>1
 %backscatter cross section
 bcs=exp(ts./10);
end