Commit 31d166dc6b30a3fa41d204011ec456df650e95a5

Authored by Jean-Luc Shaw
0 parents
Exists in master

Initial commit.

geo/dm2deci.m 0 → 100644
  1 +++ a/geo/dm2deci.m
... ... @@ -0,0 +1,23 @@
  1 +function [lond,latd] = dm2deci(londeg,lonmin,lonsec,EW,latdeg,latmin,latsec,NS)
  2 +
  3 +%
  4 +% This function converts coordinates from deg/min/sec to decimal
  5 +%
  6 +% [lond,latd] = dm2deci(londeg,lonmin,lonsec,EW,latdeg,latmin,latsec,NS)
  7 +%
  8 +% Enter numbers for longitude degrees, minutes and seconds, and a string for cardinal direction ('E' or 'W')
  9 +% followed by
  10 +% numbers for latitude degrees, minutes and seconds, and a string for cardinal direction ('N' or 'S')
  11 +%
  12 +% Written by Jean-Luc Shaw
  13 +%
  14 +
  15 +if(strmatch(NS,'N')) ; lat_sign = 1. ; end
  16 +if(strmatch(NS,'S')) ; lat_sign = -1. ; end
  17 +if(strmatch(EW,'E')) ; lon_sign = 1. ; end
  18 +if(strmatch(EW,'W')) ; lon_sign = -1. ; end
  19 +
  20 +lond = lon_sign*(londeg+lonmin./60+lonsec./3600) ;
  21 +latd = lat_sign*(latdeg+latmin./60+latsec./3600) ;
  22 +
  23 +end
... ...
geo/globeGrid.m 0 → 100644
  1 +++ a/geo/globeGrid.m
... ... @@ -0,0 +1,44 @@
  1 +function [LNG,LAT] = globeGrid(lims,sz)
  2 +% Synthax : [LNG,LAT] = globeGrid(lims,sz)
  3 +%
  4 +% Takes as input longitude and latitude limits 'lims', in format :
  5 +%
  6 +% lims = [lon_min lon_max lat_min lat_max]
  7 +%
  8 +% and a grid size 'sz' in kilometers, and generates a grid uniform in
  9 +% kilometer space, with the center of the x dimension aligned with the
  10 +% center of the area specified by 'lims'. This is mostly designed for use
  11 +% with small grids (~50-100km^2) where this representation looks almost
  12 +% regular in coordinate space and kind of "looks nice"... at least to me it
  13 +% does.
  14 +%
  15 +%
  16 +
  17 +% EARTH RADIUS
  18 +R = 6371 ;
  19 +
  20 +% convert to km
  21 +lng = [lims(1); lims(1); lims(2); lims(2)] ;
  22 +lat = [lims(3); lims(4); lims(3); lims(4)] ;
  23 +avl = mean(lng) ;
  24 +lng = lng - avl ; % move to prime meridian
  25 +
  26 +% SINUSOIDAL PROJECTION
  27 +y = ( lat*R*pi / 180 ) ;
  28 +x = ( cosd(lat).*lng*R*pi / 180 ) ;
  29 +
  30 +avy = mean(y) ;
  31 +avx = mean(x) ;
  32 +
  33 +% MAKE GRID VECTORS AROUND CENTER IN KM SPACE
  34 +xg = [flipud( [avx:-sz:min(x)]' ) ; [avx+sz:sz:max(x)]' ] ;
  35 +yg = [flipud( [avy:-sz:min(y)]' ) ; [avy+sz:sz:max(y)]' ] ;
  36 +
  37 +% GENERATE UNIFORM GRID IN KM SPACE
  38 +[X,Y] = meshgrid(xg,yg) ;
  39 +
  40 +% CONVERT BACK TO GEOGRAPHICAL COORDINATES
  41 +LAT = 180*Y./(R*pi) ;
  42 +LNG = 180*X./(R*pi*cosd(LAT)) + avl ; % moved back to average meridian
  43 +
  44 +end
0 45 \ No newline at end of file
... ...
geo/ll2area.m 0 → 100644
  1 +++ a/geo/ll2area.m
... ... @@ -0,0 +1,59 @@
  1 +function A = ll2area(lng,lat,unit)
  2 +% Synthax : A = ll2area(lng,lat,unit)
  3 +%
  4 +% Takes as input the geographical coordinate vectors for longitude 'lng'
  5 +% and latitude 'lat' in column format and returns the area inside the
  6 +% non-intersecting polygon they form as ouput 'A' in units 'unit'.
  7 +% recognized unit options are 'm' for square meters and 'km' for square
  8 +% kilometers.
  9 +%
  10 +% BASED ON:
  11 +%
  12 +% https://www.periscopedata.com/blog/polygon-area-from-latitude-and-longitude-using-sql
  13 +%
  14 +% and
  15 +%
  16 +% http://geomalgorithms.com/a01-_area.html
  17 +
  18 +% PARAMETERS
  19 +switch unit
  20 + case 'km'
  21 + R = 6371 ; % earth radius (km)
  22 + case 'm'
  23 + R = 6371000 ; % earth radius (m)
  24 +end
  25 +
  26 +% CONVERT TO XY
  27 +y = ( lat*R*pi / 180 ) ;
  28 +x = ( cosd(lat).*lng*R*pi / 180 ) ;
  29 +avx = mean(x) ;
  30 +avy = mean(y) ;
  31 +normx = x - avx ;
  32 +normy = y - avy ;
  33 +
  34 +% GET ANGLE FOR EVERY VERTEX (0-360) and convert
  35 +ang = atan2d(normy,normx); % + (-1*normx./abs(normx))*90 + 180 ;
  36 +ang( ang < 0 ) = ang( ang < 0 ) + 360 ;
  37 +ang = ang - 90;
  38 +ang = 360 - ang ;
  39 +ang(ang < 0) = ang(ang < 0) + 360 ;
  40 +ang = mod(ang,360) ;
  41 +
  42 +% SORT TO AVOID SELF INTERSECTION
  43 +[~,IA] = sort(ang,'descend') ;
  44 +x = x(IA) ;
  45 +y = y(IA) ;
  46 +
  47 +% APPEND FOR WRAPPING
  48 +x1 = x(1); xn = x(end) ;
  49 +y1 = y(1); yn = y(end) ;
  50 +x = [xn; x; x1] ;
  51 +y = [yn; y; y1] ;
  52 +
  53 +% COMPUTE THE SUM
  54 +A = 0 ;
  55 +for ii = 2:numel(x)-1
  56 + A = A + 0.5*( x(ii).*( y(ii+1) - y(ii-1) ) ) ;
  57 +end
  58 +
  59 +end
... ...
geo/llt2spd.m 0 → 100644
  1 +++ a/geo/llt2spd.m
... ... @@ -0,0 +1,49 @@
  1 +function [u,v,spd,head] = llt2spd(lon,lat,time)
  2 +
  3 +% Synthax : [u,v,spd,head] = llt2spd(lon,lat,time)
  4 +%
  5 +% Returns the speed 'spd' and it's eastward/northward components 'u' and
  6 +% 'v' in (m/s), and the heading 'head' in degrees with 0 as east increasing
  7 +% towards the north (90 degrees).
  8 +%
  9 +% Values are calculated from a latitude/longitude time series with
  10 +% coordinates in decimal degrees and time in days.
  11 +%
  12 +% Values are estimated between longitude/latitude coordinates and then
  13 +% interpolated linearly to the input 'time' vector. Begining and end
  14 +% values are extrapolated using the "pchip" method.
  15 +
  16 +%% make everything column vectors
  17 +if ~iscolumn(lon) ; lon = lon' ; end
  18 +if ~iscolumn(lat) ; lat = lat' ; end
  19 +if ~iscolumn(time) ; time = time' ; end
  20 +
  21 +%% make differential vectors
  22 +dlon = diff(lon) ;
  23 +dlat = diff(lat) ;
  24 +dt = diff(time) ;
  25 +dl = m_lldist(lon,lat)*1000 ; % (m)
  26 +
  27 +%% calculate norm of speed
  28 +spd = dl./(dt*24*60*60) ;
  29 +
  30 +%% calculate heading
  31 +head = range_pm180_2_360(atan2d(dlat,dlon)) ;
  32 +
  33 +%% decompose into eastward/northward
  34 +u = spd.*cosd(head) ;
  35 +v = spd.*sind(head) ;
  36 +
  37 +%% make the time vector
  38 +t = time(1:end-1)+0.5*dt(1);
  39 +
  40 +%% interpolate to the input time grid
  41 +u = interp1(t,u,time,'linear','extrap') ;
  42 +v = interp1(t,v,time,'linear','extrap') ;
  43 +spd = interp1(t,spd,time) ;
  44 +spd(1) = sqrt(u(1).^2+v(1).^2);
  45 +spd(end) = sqrt(u(end).^2+v(end).^2);
  46 +head = interp1(t,head,time) ;
  47 +
  48 +
  49 +end
... ...
geo/range_360_2_pm180.m 0 → 100644
  1 +++ a/geo/range_360_2_pm180.m
... ... @@ -0,0 +1,8 @@
  1 +function output = range_360_2_pm180(input)
  2 +
  3 +I = find(input > 180) ;
  4 +input(I) = input(I) - 360 ;
  5 +
  6 +output = input ;
  7 +
  8 +end
... ...
geo/range_pm180_2_360.m 0 → 100644
  1 +++ a/geo/range_pm180_2_360.m
... ... @@ -0,0 +1,8 @@
  1 +function output = range_pm180_2_360(input)
  2 +
  3 +I = find(input < 0) ;
  4 +input(I) = input(I) + 360 ;
  5 +
  6 +output = input ;
  7 +
  8 +end
... ...
geo/theta2heading.m 0 → 100644
  1 +++ a/geo/theta2heading.m
... ... @@ -0,0 +1,15 @@
  1 +
  2 +function output = theta2heading(input)
  3 +% Synthax : output = theta2heading(input)
  4 +%
  5 +% Takes as input angle vector in cartesian coordinates running counter-
  6 +% clockwise from 0 (east) to 360 degrees and transforms it into a heading
  7 +% vector running clockwise from 0 to the north to 360 degrees.
  8 +%
  9 +
  10 +input = input - 90;
  11 +input = 360 - input ;
  12 +input(input < 0) = input(input < 0) + 360 ;
  13 +output = mod(input,360) ;
  14 +
  15 +end
... ...
math/SEplot.m 0 → 100644
  1 +++ a/math/SEplot.m
... ... @@ -0,0 +1,36 @@
  1 +function [bins,bs,m,M]=SEplot(dist)
  2 +% Synthax : [bins,bs,m,M]=SEplot(dist)
  3 +%
  4 +% Produces a histogram plot of distribution 'dist' with a color code
  5 +% identifying which portions of the distribution correspond to +-1 standard
  6 +% error, +-2 standard error, +-3 standard error, and beyond. Limits are
  7 +% included to the categories and standard error is calculated with the
  8 +% built in matlab std function
  9 +
  10 +sigma = std(dist,'omitnan') ;
  11 +mdist = mean(dist,'omitnan') ;
  12 +
  13 +M = max(dist) ;
  14 +m = min(dist) ;
  15 +
  16 +bs = sigma./20 ;
  17 +bins = sort([mdist:-bs:m mdist+bs:bs:M]);
  18 +
  19 +figure ;
  20 +i = find(dist <= mdist + 1*sigma & dist >= mdist - 1.*sigma) ;
  21 +histogram(dist(i),bins,'facecolor','b') ;
  22 +
  23 +hold on
  24 +
  25 +i = find(dist <= mdist + 2*sigma & dist > mdist + 1.*sigma | ...
  26 + dist < mdist - 1*sigma & dist >= mdist - 2.*sigma) ;
  27 +histogram(dist(i),bins,'facecolor','g') ;
  28 +
  29 +i = find(dist <= mdist + 3*sigma & dist > mdist + 2.*sigma | ...
  30 + dist < mdist - 2*sigma & dist >= mdist - 3.*sigma) ;
  31 +histogram(dist(i),bins,'facecolor','r') ;
  32 +
  33 +i = find(dist <= mdist - 3*sigma | dist >= mdist + 3.*sigma) ;
  34 +histogram(dist(i),bins,'facecolor','c') ;
  35 +
  36 +end
... ...
math/SEtrunc.m 0 → 100644
  1 +++ a/math/SEtrunc.m
... ... @@ -0,0 +1,19 @@
  1 +function [dist,I] = SEtrunc(dist,thres)
  2 +% Synthax : [dist,I] = SEtrunc(dist,thres)
  3 +%
  4 +% Replaces with nan the values in dist which are outside the range
  5 +%
  6 +% +-'thres'*std('dist')
  7 +%
  8 +% where std is matlab built in function. Limits of the range are excluded.
  9 +% also returns the index values 'I' of the values nan-ed.
  10 +
  11 +sigma = std(dist,'omitnan') ;
  12 +mdist = mean(dist,'omitnan') ;
  13 +
  14 +I = find(dist < mdist - thres.*sigma | dist > mdist + thres.*sigma) ;
  15 +dist(I) = nan ;
  16 +
  17 +end
  18 +
  19 +
... ...
math/jlpca.m 0 → 100644
  1 +++ a/math/jlpca.m
... ... @@ -0,0 +1,40 @@
  1 +function [vals,vecs,stds] = jlpca(X)
  2 +% Synthax : [vals,vecs,stds] = jlpca(X)
  3 +%
  4 +% Performs principal component analysis on input matrix 'X' . Input matrix
  5 +% must be in a form where columns are different features of the data set
  6 +% and rows are repetitions of the same measurement.
  7 +%
  8 +% Also returns the standard deviation of every feature projected in the space
  9 +% of the eigenvectors found by the PCA.
  10 +%
  11 +
  12 +
  13 +[m,n] = size(X) ;
  14 +
  15 +
  16 +%% De-trend
  17 +F = repmat(nan,size(X)) ;
  18 +for ii = 1:n
  19 + F(:,ii) = X(:,ii) - mean(X(:,ii),'omitnan') ;
  20 +end
  21 +
  22 +%% Build covariance matrix
  23 +R = F'*F ;
  24 +
  25 +%% Find eigenvalues
  26 +[C,L] = eig(R) ;
  27 +
  28 +%% sort and normalise
  29 +vals = sort(diag(L),'descend') ;
  30 +
  31 +% eigenvectors in growing importance
  32 +vecs = fliplr(C) ;
  33 +
  34 +%% Project in the space of the eigenvectors
  35 +Fprime = inv(vecs)*F' ;
  36 +
  37 +%% Get the standard error in each "eigendimension"
  38 +stds = std(Fprime,[],2) ;
  39 +
  40 +end
... ...
math/nanmean.m 0 → 100644
  1 +++ a/math/nanmean.m
... ... @@ -0,0 +1,10 @@
  1 +function output = nanmean(input,varargin)
  2 +
  3 +%
  4 +% Matlab is super cheap for not including this
  5 +% in the student license. Seriously.
  6 +%
  7 +
  8 +I = find(isfinite(input)) ;
  9 +output = mean(input(I),varargin{:}) ;
  10 +end
... ...
math/nanmedian.m 0 → 100644
  1 +++ a/math/nanmedian.m
... ... @@ -0,0 +1,6 @@
  1 +function out = nanmedian(in)
  2 +
  3 +I = find(isfinite(in)) ;
  4 +out = median(in(I)) ;
  5 +
  6 +end
... ...
math/nlinfit.m 0 → 100644
  1 +++ a/math/nlinfit.m
... ... @@ -0,0 +1,33 @@
  1 +function [yfit,A] = nlinfit(rhs,x,y,pars,varargin)
  2 +%
  3 +% Synthax : [yfit,A] = nlinfit(rhs,x,y,pars,cst1,cst2,...,cstn)
  4 +%
  5 +% An idea found online and remodeled to make it more modular about how to
  6 +% fminsearch.m to perform non-linear, multiple parameter function fitting.
  7 +% Variables 'x' and 'y' are the input data, i.e., y = y(x) and must be
  8 +% vectors. Variable 'rhs' is a function handle refering to te mathematical
  9 +% form of the fitted function. For example, to fit a 1/6 power law, define:
  10 +%
  11 +% rhs = @(a,x) a(1)*x.^(1/6) + a(2) ;
  12 +%
  13 +% where 'a' is a vector formed of the parameters to fit and 'x' is the
  14 +% input independent variable. If variable 'pars' is entered as an integer
  15 +% it is interpreted as the number of parameters to fit, and sets the first
  16 +% guess for all parameters to zero. If 'pars' is entered as a vector, then
  17 +% it is interpreted as the first guess for all parameters.
  18 +%
  19 +% The function returns the fitted values at 'x' as well as the optimized
  20 +% parameter vector 'A'.
  21 +
  22 +% Is pars first guess for parameters or number of parameters
  23 +sz = size(pars) ;
  24 +if sz(1) == 1 & sz(2) == 1
  25 + start = zeros([pars 1]) ;
  26 +elseif sz(1) == 1 & sz(2) > 1 | sz(2) == 1 & sz(1) > 1
  27 + start = pars ;
  28 +end
  29 +
  30 +% Minimize parameters
  31 + A = fminsearch(@(a)sum( (y - rhs(a,x,varargin{:})).^2 ),start) ;
  32 + yfit = rhs(A,x,varargin{:}) ;
  33 +end
... ...
math/smooth2D.m 0 → 100644
  1 +++ a/math/smooth2D.m
... ... @@ -0,0 +1,43 @@
  1 +function output = smooth2D(input,hs,vs)
  2 +% Synthax : output = smooth2D(input,hs,vs)
  3 +%
  4 +% 2D moving average. The window size is 'hs' in direction j and 'vs' in
  5 +% direction i. Both 'hs' and 'vs' MUST be odd integers. Each element of
  6 +% 'output' is calculated from the nanmean of a box of size 'hs' by 'vs'
  7 +% centered on the element of corresponding indices in 'input'.
  8 +
  9 +output = repmat(nan,size(input)) ;
  10 +hpad = (hs-1)/2 ;
  11 +vpad = (vs-1)/2 ;
  12 +if vpad < 1 ; vpad = 0 ; end;
  13 +if hpad < 1 ; hpad = 0 ; end;
  14 +if iseven(vpad) ; vpad = vpad + 1 ; end
  15 +if iseven(hpad) ; hpad = hpad + 1 ; end
  16 +
  17 +[II,JJ] = size(input);
  18 +
  19 +for ii = 1:II
  20 + for jj = 1:JJ
  21 + if ii <= vpad & jj > hpad & jj <= JJ-hpad % TOP
  22 + box = input(1:ii+vpad,jj-hpad:jj+hpad) ;
  23 + elseif ii > II-vpad & jj > hpad & jj <= JJ-hpad % BOTTOM
  24 + box = input(ii-vpad:II,jj-hpad:jj+hpad) ;
  25 + elseif jj <= hpad & ii > vpad & ii <= II-vpad % LEFT
  26 + box = input(ii-vpad:ii+vpad,1:jj+hpad) ;
  27 + elseif jj > JJ-hpad & ii > vpad & ii <= II-vpad % RIGHT
  28 + box = input(ii-vpad:ii+vpad,jj-hpad:JJ) ;
  29 + elseif ii <= vpad & jj <= hpad % TOP LEFT
  30 + box = input(1:ii+vpad,1:jj+hpad) ;
  31 + elseif ii > II-vpad & jj <= hpad % BOTTOM LEFT
  32 + box = input(ii-vpad:II,1:jj+hpad) ;
  33 + elseif ii <= vpad & jj > JJ-hpad % TOP RIGHT
  34 + box = input(1:ii+vpad,jj-hpad:JJ) ;
  35 + elseif ii > II-vpad & jj > JJ-hpad % BOTTOM RIGHT
  36 + box = input(ii-vpad:II,jj-hpad:JJ) ;
  37 + else % INSIDE
  38 + box = input(ii-vpad:ii+vpad,jj-hpad:jj+hpad) ;
  39 + end
  40 + output(ii,jj) = mean(box(:),'omitnan') ;
  41 + end
  42 +end
  43 +end
... ...
math/unifrnd.m 0 → 100644
  1 +++ a/math/unifrnd.m
... ... @@ -0,0 +1,17 @@
  1 +function output = unifrnd(b_min,b_max,d_len,m,n)
  2 +
  3 +% Synthax : output = unifrnd(b_min,b_max,d_len,m,n)
  4 +%
  5 +% Imitates the unifrnd function from the statistics toolbox. Generates a
  6 +% 'm' by 'n' matrix of values chosen from a uniform distribution of minimum
  7 +% 'b_min' and maximum 'b_max' . The parameter 'd_len' controls the number
  8 +% of elements in the uniform distribution the 'output' values are chosen
  9 +% from.
  10 +%
  11 +
  12 +dist = linspace(b_min,b_max,d_len)' ;
  13 +I = randi([1 d_len],[m n]) ;
  14 +
  15 +output = dist(I) ;
  16 +
  17 +end
0 18 \ No newline at end of file
... ...
math/vvangle.m 0 → 100644
  1 +++ a/math/vvangle.m
... ... @@ -0,0 +1,21 @@
  1 +function theta = vvangle(v1,v2)
  2 +% Synthax : theta = vvangle(v1,v2)
  3 +%
  4 +% Get the absolute angle between two line vectors, or between the vectors
  5 +% described by the lines v1 and v2.
  6 +%
  7 +
  8 +%% make sure the sizes are compatible
  9 +if ~( isequal(size(v1),size(v2)) || isvector(v1) && isvector(v2) && numel(v1) == numel(v2) )
  10 + disp(' Error : v1 and v2 have different dimensions!') ;
  11 + return ;
  12 +end
  13 +
  14 +%% get the vector norms
  15 +nv1 = sum(abs(v1).^2,2).^(1/2) ;
  16 +nv2 = sum(abs(v2).^2,2).^(1/2) ;
  17 +
  18 +%% calculate the angle
  19 +theta = acosd( ( dot(v1,v2,2) ) ./ (nv1.*nv2) ) ;
  20 +
  21 +end
0 22 \ No newline at end of file
... ...
old/ADCP_cleanup.m 0 → 100644
  1 +++ a/old/ADCP_cleanup.m
... ... @@ -0,0 +1,859 @@
  1 +function ADCP_cleanup(ADCP_file_path,ADCP_file_name,BATH_file,CTD_file,GPS_file,strtsamp,stopsamp,theta,corrtag,CTDtag,WD,zerolon,zerolat)
  2 +
  3 +disp('========== 1) ADCP_cleanup ==========') ;
  4 +
  5 +tic
  6 +%% PARAMETERS
  7 +paperwidth = 20 ;
  8 +paperheight = 6 ;
  9 +
  10 +%% OUTPUT FILE TAGS
  11 +CC = ['CC' strrep(num2str(theta),'.','') 'd'] ;
  12 +
  13 +%% LOAD data
  14 +disp('Loading data ...')
  15 +load([WD ADCP_file_path ADCP_file_name]) ;
  16 +bathystruc = load(BATH_file) ;
  17 +bathyfield = fieldnames(bathystruc) ;
  18 +BATHY = getfield(bathystruc,bathyfield{:}) ;
  19 +
  20 +% dataset decimation (for testing)
  21 +loaded = 1:1:numel(Sens.dnum) ;
  22 +
  23 +%% CREATE GRAPHICS AND DATA FOLDERS
  24 +if 7 == exist([WD 'figs/ADCP_cleanup'])
  25 + disp('Graphics folder found.') ;
  26 +else
  27 + disp('Creating graphics folder : figs/ADCP_cleanup')
  28 + mkdir([WD 'figs/ADCP_cleanup']);
  29 +end
  30 +
  31 +if 7 == exist([WD 'data'])
  32 + disp('data folder found.') ;
  33 +else
  34 + disp('Creating data folder : data')
  35 + mkdir([WD 'data']);
  36 +end
  37 +
  38 +%% temps ADCP
  39 +I = find(Sens.dnum(loaded) < strtsamp | Sens.dnum(loaded) > stopsamp) ;
  40 +loaded(I) = [] ;
  41 +time = Sens.dnum(loaded) ;
  42 +
  43 +%% matrices des vitesses
  44 +
  45 +u_raw = Wt.vel(loaded,:,1)' ; % m/s
  46 +v_raw = Wt.vel(loaded,:,2)' ; % m/s
  47 +w_raw = Wt.vel(loaded,:,3)' ; % m/s
  48 +disp('Done')
  49 +
  50 +%% vitesse du bateau
  51 +disp('Making boat speed matrices ...')
  52 +fid = fopen([WD GPS_file]) ;
  53 + frmt = ['%s%s%f%f%s%s' repmat('%s',[1 23])] ;
  54 + data = textscan(fid,frmt,'headerlines',49,'delimiter',',') ;
  55 +fclose(fid) ;
  56 +
  57 +[boat_tim,IA,~] = unique(datenum(cell2mat(data{6}),'yyyy-mm-ddTHH:MM:SS'));
  58 +boat_lon = data{4}(IA) ;
  59 +boat_lat = data{3}(IA) ;
  60 +
  61 +% calculer la vitesse du bateau
  62 +[boat_u,boat_v,boat_spd,boat_head] = llt2spd(boat_lon,boat_lat,boat_tim) ;
  63 +
  64 +boat_acc = sqrt(gradient(boat_u,boat_tim*(24*3600)).^2 + gradient(boat_v,boat_tim*(24*3600)).^2) ;
  65 +
  66 +% interpoler sur le temps de l ADCP
  67 +boat_lon = interp1(boat_tim,boat_lon,time) ;
  68 +boat_lat = interp1(boat_tim,boat_lat,time) ;
  69 +boat_u = interp1(boat_tim,boat_u,time) ;
  70 +boat_v = interp1(boat_tim,boat_v,time) ;
  71 +boat_head = interp1(boat_tim,boat_head,time) ;
  72 +boat_acc = interp1(boat_tim,boat_acc,time) ;
  73 +boat_spd = interp1(boat_tim,boat_spd,time) ;
  74 +
  75 +% creer les matrices de vitesse de bateau de la taille de vitesses raw
  76 +boat_u_mat = repmat(boat_u',[numel(u_raw(:,1)) 1]) ;
  77 +boat_v_mat = repmat(boat_v',[numel(v_raw(:,1)) 1]) ;
  78 +
  79 +%% positions du centre des bins
  80 +% une profondeur du poisson de 1 m est supposee.
  81 +z = 1 + Info.cell1 + 0.5*Info.cell ...
  82 + + [0 : Info.cell : 93*Info.cell] ; % ecrit ainsi par souci de clarte
  83 +
  84 +%% raw data depths
  85 +depth = BATHY(boat_lon,boat_lat) ;
  86 +clear BATHY ;
  87 +
  88 +%% PRINT THE BOAT SPEED MATRICES
  89 +disp('Printing boat speed matrices ... ')
  90 +figure('visible','off');
  91 +
  92 +pcolor(time,z,boat_u_mat)
  93 +hold on
  94 +plot(time,depth*cosd(25),'k')
  95 +plot(time,depth,'k--')
  96 +datetick('x','HH:MM')
  97 +xlabel('Time')
  98 +ylabel('Depth (m)')
  99 +shading flat ;
  100 +axis ij;
  101 +ylim([0 80]) ; xlim([min(time) max(time)]) ;
  102 +caxis([-1 1])
  103 +jlcolorbar('u') ;
  104 +
  105 +set(gcf,'PaperUnits','centimeters');
  106 +set(gcf,'PaperSize',[paperwidth paperheight]);
  107 +set(gcf,'PaperPosition',[0 0 paperwidth paperheight]);
  108 +print('-dpng', '-r300',[WD 'figs/ADCP_cleanup/u_boat_speed_' CC '_' corrtag '.png']);
  109 +close;
  110 +
  111 +figure('visible','off');
  112 +
  113 +pcolor(time,z,boat_v_mat)
  114 +hold on
  115 +plot(time,depth*cosd(25),'k')
  116 +plot(time,depth,'k--')
  117 +datetick('x','HH:MM')
  118 +xlabel('Time')
  119 +ylabel('Depth (m)')
  120 +shading flat ;
  121 +axis ij;
  122 +ylim([0 80]) ; xlim([min(time) max(time)]) ;
  123 +caxis([-1 1])
  124 +jlcolorbar('v') ;
  125 +
  126 +set(gcf,'PaperUnits','centimeters');
  127 +set(gcf,'PaperSize',[paperwidth paperheight]);
  128 +set(gcf,'PaperPosition',[0 0 paperwidth paperheight]);
  129 +print('-dpng', '-r300',[WD 'figs/ADCP_cleanup/v_boat_speed_' CC '_' corrtag '.png']);
  130 +close;
  131 +disp('Done.') ;
  132 +
  133 +%% PRINT THE RAW DATA
  134 +disp('Printing the raw data ... ')
  135 +figure('visible','off');
  136 +
  137 +pcolor(time,z,u_raw)
  138 +hold on
  139 +plot(time,depth*cosd(25),'k')
  140 +plot(time,depth,'k--')
  141 +datetick('x','HH:MM')
  142 +xlabel('Time')
  143 +ylabel('Depth (m)')
  144 +shading flat ;
  145 +axis ij;
  146 +ylim([0 80]) ; xlim([min(time) max(time)]) ;
  147 +caxis([-1 1])
  148 +jlcolorbar('u') ;
  149 +
  150 +set(gcf,'PaperUnits','centimeters');
  151 +set(gcf,'PaperSize',[paperwidth paperheight]);
  152 +set(gcf,'PaperPosition',[0 0 paperwidth paperheight]);
  153 +print('-dpng', '-r300',[WD 'figs/ADCP_cleanup/u_raw_' CC '_' corrtag '.png']);
  154 +close;
  155 +
  156 +figure('visible','off');
  157 +
  158 +pcolor(time,z,v_raw)
  159 +hold on
  160 +plot(time,depth*cosd(25),'k')
  161 +plot(time,depth,'k--')
  162 +datetick('x','HH:MM')
  163 +xlabel('Time')
  164 +ylabel('Depth (m)')
  165 +shading flat ;
  166 +axis ij;
  167 +ylim([0 80]) ; xlim([min(time) max(time)]) ;
  168 +caxis([-1 1])
  169 +jlcolorbar('v') ;
  170 +
  171 +set(gcf,'PaperUnits','centimeters');
  172 +set(gcf,'PaperSize',[paperwidth paperheight]);
  173 +set(gcf,'PaperPosition',[0 0 paperwidth paperheight]);
  174 +print('-dpng', '-r300',[WD 'figs/ADCP_cleanup/v_raw_' CC '_' corrtag '.png']);
  175 +close;
  176 +disp('Done.')
  177 +
  178 +%% rotation corrective des vitesses mesurees
  179 +% une rotation de 36 degree correspond a deux fois la declinaison
  180 +% magnetique. L hypothese est que la valeur de -18.x a ete utilisee au lieu
  181 +% de la valeur de 18.x . Suite utilisation d'un script qui test les angles
  182 +% de 0 a 360 degres et minimise la norme de u et v, la valeur de rotation
  183 +% optimal semble etre 32 degres. Un script qui cherche la difference
  184 +% moyenne entre le heading trouve par les vitesses du bateau et celles de l
  185 +% adcp produit un angle optimal de 27.3 degres pour sa part. Toutefois, cet
  186 +% angle de rotation produit encore des artefacts de vitesse de bateau.
  187 +% Tatonnement fournit 25 degres comme l'angle de rotation optimal
  188 +disp('Compass correct rotation ...')
  189 +u_rot = u_raw.*cosd(theta) - v_raw.*sind(theta) ;
  190 +v_rot = u_raw.*sind(theta) + v_raw.*cosd(theta) ;
  191 +disp('Done.')
  192 +
  193 +clear u_raw ; clear v_raw ;
  194 +
  195 +%% PRINT THE ROTATED DATA
  196 +disp('Printing rotated data ... ')
  197 +figure('visible','off');
  198 +
  199 +pcolor(time,z,u_rot)
  200 +hold on
  201 +plot(time,depth*cosd(25),'k')
  202 +plot(time,depth,'k--')
  203 +datetick('x','HH:MM')
  204 +xlabel('Time')
  205 +ylabel('Depth (m)')
  206 +shading flat ;
  207 +axis ij;
  208 +ylim([0 80]) ; xlim([min(time) max(time)]) ;
  209 +caxis([-1 1])
  210 +jlcolorbar('u') ;
  211 +
  212 +set(gcf,'PaperUnits','centimeters');
  213 +set(gcf,'PaperSize',[paperwidth paperheight]);
  214 +set(gcf,'PaperPosition',[0 0 paperwidth paperheight]);
  215 +print('-dpng', '-r300',[WD 'figs/ADCP_cleanup/u_rot_' CC '_' corrtag '.png']);
  216 +close;
  217 +
  218 +figure('visible','off');
  219 +
  220 +pcolor(time,z,v_rot)
  221 +hold on
  222 +plot(time,depth*cosd(25),'k')
  223 +plot(time,depth,'k--')
  224 +datetick('x','HH:MM')
  225 +xlabel('Time')
  226 +ylabel('Depth (m)')
  227 +shading flat ;
  228 +axis ij;
  229 +ylim([0 80]) ; xlim([min(time) max(time)]) ;
  230 +caxis([-1 1])
  231 +jlcolorbar('v') ;
  232 +
  233 +set(gcf,'PaperUnits','centimeters');
  234 +set(gcf,'PaperSize',[paperwidth paperheight]);
  235 +set(gcf,'PaperPosition',[0 0 paperwidth paperheight]);
  236 +print('-dpng', '-r300',[WD 'figs/ADCP_cleanup/v_rot' CC '_' corrtag '.png']);
  237 +close;
  238 +disp('Done.')
  239 +
  240 +%% retrait des donnees corr < 64
  241 +
  242 +switch corrtag
  243 + case 'CF64'
  244 + disp('Removing uncorrelated ...')
  245 + I = find(Wt.corr(loaded,:,1)' < 64 | Wt.corr(loaded,:,2)' < 64 ...
  246 + | Wt.corr(loaded,:,3)' < 64 | Wt.corr(loaded,:,4)' < 64 ) ;
  247 + u_rot(I) = nan ;
  248 + v_rot(I) = nan ;
  249 + w_raw(I) = nan ;
  250 + disp('Done.')
  251 +
  252 + clear Wt ; clear Info ; clear Sens ;
  253 +
  254 +%% PRINT THE DATA AFTER REMOVAL OF UNCORELLATED DATA
  255 + disp('Printing the correlated data ... ')
  256 + figure('visible','off');
  257 +
  258 + pcolor(time,z,u_rot)
  259 + hold on
  260 + plot(time,depth*cosd(25),'k')
  261 + plot(time,depth,'k--')
  262 + datetick('x','HH:MM')
  263 + xlabel('Time')
  264 + ylabel('Depth (m)')
  265 + shading flat ;
  266 + axis ij;
  267 + ylim([0 80]) ; xlim([min(time) max(time)]) ;
  268 + caxis([-1 1])
  269 + jlcolorbar('u') ;
  270 +
  271 + set(gcf,'PaperUnits','centimeters');
  272 + set(gcf,'PaperSize',[paperwidth paperheight]);
  273 + set(gcf,'PaperPosition',[0 0 paperwidth paperheight]);
  274 + print('-dpng', '-r300',[WD 'figs/ADCP_cleanup/u_corr_' CC '_' corrtag '.png']);
  275 + close;
  276 +
  277 + figure('visible','off');
  278 +
  279 + pcolor(time,z,v_rot)
  280 + hold on
  281 + plot(time,depth*cosd(25),'k')
  282 + plot(time,depth,'k--')
  283 + datetick('x','HH:MM')
  284 + xlabel('Time')
  285 + ylabel('Depth (m)')
  286 + shading flat ;
  287 + axis ij;
  288 + ylim([0 80]) ; xlim([min(time) max(time)]) ;
  289 + caxis([-1 1])
  290 + jlcolorbar('v') ;
  291 +
  292 + set(gcf,'PaperUnits','centimeters');
  293 + set(gcf,'PaperSize',[paperwidth paperheight]);
  294 + set(gcf,'PaperPosition',[0 0 paperwidth paperheight]);
  295 + print('-dpng', '-r300',[WD 'figs/ADCP_cleanup/v_corr_' CC '_' corrtag '.png']);
  296 + close;
  297 + disp('Done.')
  298 + case 'NCF'
  299 +end
  300 +
  301 +%% correction des vitesses pour la vitesse du bateau
  302 +disp('Boat speed correction ...')
  303 +u = u_rot + boat_u_mat ;
  304 +v = v_rot + boat_v_mat ;
  305 +w = w_raw ;
  306 +disp('Done.')
  307 +
  308 +%% PRINT THE BOAT-CORRECTED DATA
  309 +disp('Printing the boat speed corrected data ... ')
  310 +figure('visible','off');
  311 +
  312 +pcolor(time,z,u)
  313 +hold on
  314 +plot(time,depth*cosd(25),'k')
  315 +plot(time,depth,'k--')
  316 +datetick('x','HH:MM')
  317 +xlabel('Time')
  318 +ylabel('Depth (m)')
  319 +shading flat ;
  320 +axis ij;
  321 +ylim([0 80]) ; xlim([min(time) max(time)]) ;
  322 +caxis([-1 1])
  323 +jlcolorbar('u') ;
  324 +
  325 +set(gcf,'PaperUnits','centimeters');
  326 +set(gcf,'PaperSize',[paperwidth paperheight]);
  327 +set(gcf,'PaperPosition',[0 0 paperwidth paperheight]);
  328 +print('-dpng', '-r300',[WD 'figs/ADCP_cleanup/u_boat_' CC '_' corrtag '.png']);
  329 +close;
  330 +
  331 +figure('visible','off');
  332 +
  333 +pcolor(time,z,v)
  334 +hold on
  335 +plot(time,depth*cosd(25),'k')
  336 +plot(time,depth,'k--')
  337 +datetick('x','HH:MM')
  338 +xlabel('Time')
  339 +ylabel('Depth (m)')
  340 +shading flat ;
  341 +axis ij;
  342 +ylim([0 80]) ; xlim([min(time) max(time)]) ;
  343 +caxis([-1 1])
  344 +jlcolorbar('v') ;
  345 +
  346 +set(gcf,'PaperUnits','centimeters');
  347 +set(gcf,'PaperSize',[paperwidth paperheight]);
  348 +set(gcf,'PaperPosition',[0 0 paperwidth paperheight]);
  349 +print('-dpng', '-r300',[WD 'figs/ADCP_cleanup/v_boat_' CC '_' corrtag '.png']);
  350 +close;
  351 +disp('Done.')
  352 +
  353 +
  354 +%% REMOVE ADCP DATA FROM Acceleration
  355 +
  356 +switch CTDtag
  357 + case 'CTDout'
  358 +fid = fopen([WD CTD_file]);
  359 + frmt = '%s%f%f%f%f' ;
  360 + data = textscan(fid,frmt,'headerlines',1,'delimiter',';');
  361 +fclose(fid);
  362 +
  363 +statname = data{1} ;
  364 +statstrt = data{4} ;
  365 +statstop = data{5} ;
  366 +
  367 +for ii = 1:numel(statname)
  368 + I = find(time < statstop(ii) & time > statstrt(ii)) ;
  369 + u(:,I) = nan ;
  370 + v(:,I) = nan ;
  371 + w(:,I) = nan ;
  372 +end
  373 +end
  374 +
  375 +NN1 = sqrt(u.^2+v.^2) ;
  376 +NN2 = sqrt(u_rot.^2+v_rot.^2) ;
  377 +% and speed which are bigger since adding boat speed
  378 +I = find(NN1 > NN2) ;
  379 +%u(I) = nan ;
  380 +%v(I) = nan ;
  381 +%w(I) = nan ;
  382 +disp('Done.')
  383 +
  384 +%% FILTER BOAT TURNS
  385 +
  386 +N = 250 ;
  387 +B = repmat(1./N,[1 N]) ;
  388 +A = 1 ;
  389 +boat_head_sm = filtfilt(B,A,boat_head) ;
  390 +
  391 +[~,I1] = SEtrunc(gradient(boat_head_sm),1) ;
  392 +boat_head_clr = boat_head ;
  393 +boat_head_clr(I1) = nan;
  394 +[~,I2] = SEtrunc(gradient(boat_head_clr),0.8) ;
  395 +I = sort([I1 ; I2]);
  396 +
  397 +%u(:,I) = nan ;
  398 +%v(:,I) = nan ;
  399 +%w(:,I) = nan ;
  400 +
  401 +%% PRINT THE CTD REMOVED DATA
  402 +disp('Printing the CTD removed data ... ')
  403 +figure('visible','off');
  404 +
  405 +pcolor(time,z,u)
  406 +hold on
  407 +plot(time,depth*cosd(25),'k')
  408 +plot(time,depth,'k--')
  409 +datetick('x','HH:MM')
  410 +xlabel('Time')
  411 +ylabel('Depth (m)')
  412 +shading flat ;
  413 +axis ij;
  414 +ylim([0 80]) ; xlim([min(time) max(time)]) ;
  415 +caxis([-1 1])
  416 +jlcolorbar('u') ;
  417 +
  418 +set(gcf,'PaperUnits','centimeters');
  419 +set(gcf,'PaperSize',[paperwidth paperheight]);
  420 +set(gcf,'PaperPosition',[0 0 paperwidth paperheight]);
  421 +print('-dpng', '-r300',[WD 'figs/ADCP_cleanup/u_ctdout_' CC '_' corrtag '.png']);
  422 +close;
  423 +
  424 +figure('visible','off');
  425 +
  426 +pcolor(time,z,v)
  427 +hold on
  428 +plot(time,depth*cosd(25),'k')
  429 +plot(time,depth,'k--')
  430 +datetick('x','HH:MM')
  431 +xlabel('Time')
  432 +ylabel('Depth (m)')
  433 +shading flat ;
  434 +axis ij;
  435 +ylim([0 80]) ; xlim([min(time) max(time)]) ;
  436 +caxis([-1 1])
  437 +jlcolorbar('v') ;
  438 +
  439 +set(gcf,'PaperUnits','centimeters');
  440 +set(gcf,'PaperSize',[paperwidth paperheight]);
  441 +set(gcf,'PaperPosition',[0 0 paperwidth paperheight]);
  442 +print('-dpng', '-r300',[WD 'figs/ADCP_cleanup/v_ctdout_' CC '_' corrtag '.png']);
  443 +close;
  444 +disp('Done.')
  445 +
  446 +clear u_rot ; clear v_rot ; clear w_raw ;
  447 +clear boat_u_mat ;
  448 +clear boat_v_mat;
  449 +clear boat_u ;
  450 +clear boat_v ;
  451 +
  452 +%% Build mean transect
  453 +disp('Projection along mean transect ...')
  454 +rlon = boat_lon ;
  455 +rlat = boat_lat ;
  456 +
  457 +mlon = linspace(min(rlon),max(rlon),300) ;
  458 +P = polyfit(rlon,rlat,1) ;
  459 +mlat = P(1)*mlon + P(2) ;
  460 +
  461 +% figure
  462 +% plot(rlon,rlat,'r.','markersize',0.1)
  463 +% hold on
  464 +% plot(mlon,mlat,'k.')
  465 +
  466 +%% Projection of the coordinates on the mean transect
  467 +a = -P(1) ; b = 1 ; c = -P(2) ;
  468 +plon = (b*( b*rlon-a*rlat) - a*c ) ./ ( a*a + b*b ) ;
  469 +plat = (a*(-b*rlon+a*rlat) - b*c ) ./ ( a*a + b*b ) ;
  470 +disp('Done.')
  471 +
  472 +%% PRINT THE FITTED TRANSECT
  473 +disp('Disp printing the fitted transect')
  474 +figure('visible','off')
  475 +plot(rlon,rlat,'-','color',[0.7 0.7 0.7])
  476 +hold on
  477 +plot(plon,plat,'k-')
  478 +xlabel('Longitude')
  479 +ylabel('Latitude')
  480 +
  481 +set(gcf,'PaperUnits','centimeters');
  482 +set(gcf,'PaperSize',[10 10]);
  483 +set(gcf,'PaperPosition',[0 0 10 10]);
  484 +print('-dpng', '-r300',[WD 'figs/ADCP_cleanup/mean_transect' CC '_' corrtag '.png']);
  485 +close;
  486 +disp('Done.') ;
  487 +
  488 +%% Remove data points further than 200 m from the transect
  489 +disp('Remove points too far from mean transect ... ')
  490 +for ii = 1:numel(rlon)
  491 + proj_dist = m_lldist([rlon(ii) plon(ii)],[rlat(ii) plat(ii)]) ;
  492 +end
  493 +
  494 +Igone = find(proj_dist > 0.2) ;
  495 +u(Igone,:) = nan ;
  496 +v(Igone,:) = nan ;
  497 +w(Igone,:) = nan ;
  498 +disp('Done.')
  499 +
  500 +%% PRINT DATA AFTER REMOVING POINTS TOO FAR FROM MEAN TRANSECT
  501 +disp('Printing the data after removal of casts more than 200m from the mean transect ...') ;
  502 +figure('visible','off');
  503 +
  504 +pcolor(time,z,u)
  505 +hold on
  506 +plot(time,depth*cosd(25),'k')
  507 +plot(time,depth,'k--')
  508 +datetick('x','HH:MM')
  509 +xlabel('Time')
  510 +ylabel('Depth (m)')
  511 +shading flat ;
  512 +axis ij;
  513 +ylim([0 80]) ; xlim([min(time) max(time)]) ;
  514 +caxis([-1 1])
  515 +jlcolorbar('u') ;
  516 +
  517 +set(gcf,'PaperUnits','centimeters');
  518 +set(gcf,'PaperSize',[paperwidth paperheight]);
  519 +set(gcf,'PaperPosition',[0 0 paperwidth paperheight]);
  520 +print('-dpng', '-r300',[WD 'figs/ADCP_cleanup/u_toofar_' CC '_' corrtag '.png']);