function [fix, uv] = adcp_nav(cfg, profs, fixes)

fixes.dd = fixes.dd(:).';
fixes.x = fixes.x(:).';
fixes.y = fixes.y(:).';

goodmask = ((profs.pg > cfg.min_pg) & (profs.pf == 0));
profs.u(~goodmask) = NaN;
profs.v(~goodmask) = NaN;

[nd, nt] = size(profs.u);

uvf = zeros(nd, nt);
filt_frac = uvf;


ifix = zeros(nt, 1);
abs_min = ifix;
for ii = 1:nt,
   absdt = abs(fixes.dd - profs.dd(ii));
   i_closest = find(absdt == min(absdt));
   ifix(ii) = i_closest(1);
   abs_min(ii) = absdt(i_closest);
end

ibad = abs_min > (cfg.fix_t_mismatch / 86400);


fix.dd = fixes.dd(ifix);
fix.x = fixes.x(ifix);
fix.y = fixes.y(ifix);

fix.dd(ibad) = profs.dd(ibad);
fix.x(ibad) = NaN;
fix.y(ibad) = NaN;

if 1,  % interpolate missing fixes.    Dangerous!
   fix.x(ibad) = table1([fix.dd(~ibad).', fix.x(~ibad).'], fix.dd(ibad)).';
   fix.y(ibad) = table1([fix.dd(~ibad).', fix.y(~ibad).'], fix.dd(ibad)).';
end


fix.dt = diff(fix.dd) * 86400;
fix.y_av = 0.5 * (fix.y(1:(end-1)) + fix.y(2:end));
fix.dx = lon_to_m(diff(fix.x), fix.y_av);
fix.dy = lat_to_m(diff(fix.y), fix.y_av);
fix.u = [NaN fix.dx ./ fix.dt];
fix.v = [NaN fix.dy ./ fix.dt];

uv.raw = (profs.u + repmat(fix.u, nd, 1) ) ...
           + i * (profs.v + repmat(fix.v, nd, 1));

for ii = 1:nd,
   [uvf(ii, :), filt_frac(ii, :)] = bl_filt(uv.raw(ii, :), cfg.bl_half_width);
end

uvres = uv.raw - uvf;            % NaNs where there is no data.
%dt = diff(profs.dd) * 86400;
dt = diff(fix.dd) * 86400;
dt = [ (dt(1) - diff(dt(1:2))), dt];

uvdt = uvres .* repmat(dt, nd, 1);
nan_mask = isnan(uvdt);
uvdt(nan_mask) = 0;                  % Zero where there is no data.
xy_adjust = cumsum(uvdt, 2);

xy_hp = zeros(nd, nt);    % Hi-pass filtered position adjustments
xy_frac = zeros(nd, nt);
for ii = 1:nd,
   xy_hp(ii, :) = xy_adjust(ii, :) ...
                   - bl_filt(xy_adjust(ii, :), cfg.xy_bl_half_width);
   [xx, xy_frac(ii, :)] = bl_filt(uvres(ii,:), cfg.xy_bl_half_width);
                           % still has NaNs
end

ii = (cfg.ref_mid + 1):cfg.ref_bot;
tmp_mask = logical(ones(nd, nt));
tmp_mask(ii, :) = (xy_frac(ii,:) < cfg.min_xy_frac) | isnan(xy_frac(ii,:));
xy_hp(tmp_mask) = NaN;

ii = cfg.ref_top:cfg.ref_bot;
[xy_adj.mean, xy_adj.std, xy_adj.n] = mstdgap(xy_hp(ii, :));
% We don't need to calculate the median all the time,
% unless we want to use it for checking or editing.

fix.x_adj = fix.x - m_to_lon(real(xy_adj.mean), fix.y);
fix.y_adj = fix.y - m_to_lat(imag(xy_adj.mean), fix.y);

% If we don't have a valid adjustment for a fix, leave
% the original fix.
ibad = isnan(fix.x_adj);
fix.x_adj(ibad) = fix.x(ibad);
fix.y_adj(ibad) = fix.y(ibad);

fix.dx_adj = lon_to_m(diff(fix.x_adj), fix.y_av);
fix.dy_adj = lat_to_m(diff(fix.y_adj), fix.y_av);
fix.u_adj = [NaN fix.dx_adj ./ fix.dt];
fix.v_adj = [NaN fix.dy_adj ./ fix.dt];

uv.adj = (profs.u + repmat(fix.u_adj, nd, 1) ) ...
          + i * (profs.v + repmat(fix.v_adj, nd, 1));



