
% -- 
% Jeff Sevadjian
% Monterey Bay Aquarium Research Institute
% 7700 Sandholdt Rd
% Moss Landing, CA 95039, USA
% ph: +1 831-775-1888

% Human-in-the-loop QC procedure to generate final QC'd WG data set.
% Strongly recommend entering commands from this script manually a few
%  lines at a time as opposed to running the entire script all at once.

% All the 'processing' (applying cal's, deriving of engineering units, etc.)
%  is now done without human input in python scripts, either in
%  real-time (makeWGwebQC_wgTiny.py), or post-cruise (loadWGdata_wgTiny.py).
% This Matlab script is used only to identify and remove bad data.

% Outputs final .csv files in the /QC directory
% A final .nc file (merged to a common 10-min time stamp) needs to be
%  created after this script is run using makeWGnetCDF_wgTiny.py.

%depl info
 veh = 'wgSparky';
 dep = '20180905';

%directories for post-cruise and QC'd data
 atlas = '//atlas.shore.mbari.org/';
 mydirPC = [atlas 'WaveGlider/deployment_data/' veh '/' dep '/postCruise/'];
 mydirQC = [atlas 'WaveGlider/deployment_data/' veh '/' dep '/QC/'];
 clear veh dep;

%create /QC dir if doesn't exist
 if ~exist(mydirQC,'dir')
   mkdir(mydirQC);
 end

%paths to WG, M1 code
 addpath([atlas 'jsevadjian/code/WaveGlider/QC code/']);
 addpath([atlas 'jsevadjian/M-buoy/code/']);

%--%

%read-in postCruise .csv files
% NaN zeros, convert time stamp, interp position
 dn = datenum([1970 1 1]);
 %Position
  Position = csvread([mydirPC 'Position.csv'],1,0);
  Position(Position==0) = NaN;
  Position(:,1) = dn + Position(:,1)/86400/1000;
 %CTD1 [T, S, O2]
  CTD1 = csvread([mydirPC 'CTD1.csv'],1,0);
  CTD1(CTD1==0) = NaN;
  CTD1(:,1) = dn + CTD1(:,1)/86400/1000;
  CTD1(:,5) = interp1(Position(:,1),Position(:,2),CTD1(:,1));
  CTD1(:,6) = interp1(Position(:,1),Position(:,3),CTD1(:,1));
 %CTD2 [T, S, O2]
  CTD2 = csvread([mydirPC 'CTD2.csv'],1,0);
  CTD2(CTD2==0) = NaN;
  CTD2(:,1) = dn + CTD2(:,1)/86400/1000;
  CTD2(:,5) = interp1(Position(:,1),Position(:,2),CTD2(:,1));
  CTD2(:,6) = interp1(Position(:,1),Position(:,3),CTD2(:,1));

 %Eco-Puck [fluor, bb470, bb650]
  EP = csvread([mydirPC 'EcoPuck.csv'],1,0);
  EP(EP==0) = NaN;
  EP(:,1) = dn + EP(:,1)/86400/1000;
  EP(:,5) = interp1(Position(:,1),Position(:,2),EP(:,1));
  EP(:,6) = interp1(Position(:,1),Position(:,3),EP(:,1));
 %MET [airPress, airTemp]
  MET = csvread([mydirPC 'MET.csv'],1,0);
  MET(MET==0) = NaN;
  MET(:,1) = dn + MET(:,1)/86400/1000;
  MET(:,4) = interp1(Position(:,1),Position(:,2),MET(:,1));
  MET(:,5) = interp1(Position(:,1),Position(:,3),MET(:,1));
 %MET wind [windDir, windSpd]
  METw = csvread([mydirPC 'METwind.csv'],1,0);
  METw(METw==0) = NaN;
  METw(:,1) = dn + METw(:,1)/86400/1000;
  METw(:,4) = interp1(Position(:,1),Position(:,2),METw(:,1));
  METw(:,5) = interp1(Position(:,1),Position(:,3),METw(:,1));
 %TagID [tagID]
%   TagID = csvread([mydirPC 'tagID.csv'],1,0); %errors if no data

%Plot all sensor data in one fig
% This is to compare different data sets for simultaneous 'events' -
%  i.e. if there is a spike in O2 and pCO2w at the same time, they 
%  are both likely to be 'real.' This is to aid removal of data which
%  is implemented in the individual sensor break-out figures.
%  qcWG_plotAll(Position,CTD1,CTD2,EP,MET,METw);

%tBeg, tEnd should already be finalized in WG_cal_config.xlsx

%plot map
 coast = dlmread([atlas 'jsevadjian/GIS/montereyBay.txt']);
 figure; hold on;
 plot(coast(:,1),coast(:,2),'k');
 scatter(Position(:,2),Position(:,3),3,Position(:,1),'filled');
 colormap(jet);
 plot(-122.02203,36.75060,'k.','MarkerSize',10); %M1
 plot(-122.378,36.697,'k.','MarkerSize',10); %M2
 plot(-121.847,36.797,'k.','MarkerSize',10); %C1
 set(gca,'XLim',[min(Position(:,2)) max(Position(:,2))] + 0.2*[-1 1]);
 set(gca,'YLim',[min(Position(:,3)) max(Position(:,3))] + 0.2*[-1 1]);
 set(gca,'DataAspectRatio',[1 cos(nanmean(get(gca,'YLim')/180*pi)) 1]);
 box on;
 clear coast;

%--%

%load M1 data
 % See //atlas/jsevadjian/M-Buoy/M1_cal_config.xlsx
  M1dep = '201607'; %'201607' or '201507';
%   M1co2cal = [ ...
%     datenum([2015 7 30 0 0 0]), datenum([2015 10 1 20 0 0]), -12.7455, 0.4090, 0.9983, 0.0012; ...
%     datenum([2015 10 1 23 0 0]), datenum([2015 8 29 0 0 0]), -4.7736, 0.2689, 1.0355, -0.0023 ];
  M1co2cal = [ ...
    datenum([2016 8 29 0 0 0]), now, 3.5927 0.1272 1.0254 -0.003 ];
%   M1pHcal = [ ...
%     datenum([2015 7 30 19 0 0; 2015 10 23 18 50 0])', -0.378917, 284.99; ...
%     datenum([2015 10 23 19 0 0; 2016 8 29 19 0 0])', -0.384977, 279.15 ];
  M1pHcal = [ ...
    datenum([2016 8 29 0 0 0]), datenum([2017 3 14 18 40 0]), -0.404050 294.19; ...
    datenum([2017 3 14 18 40 1]), now, -0.400226, 293.81 ];

 %load data
  M1gps = read_M1_GPS_full('M1',M1dep);
  %CTD
   M1ctd = load_M1_CTD('M1',M1dep);
   M1ctd.lon = interp1(M1gps(:,1), M1gps(:,2), M1ctd.time);
   M1ctd.lat = interp1(M1gps(:,1), M1gps(:,3), M1ctd.time);
  %O2
   M1o2 = load_M1_O2('m1-slave1',M1dep,M1ctd);
   M1o2.lon = interp1(M1gps(:,1), M1gps(:,2), M1o2.time);
   M1o2.lat = interp1(M1gps(:,1), M1gps(:,3), M1o2.time);
  %pH
   M1pH = load_M1_pH('m1-slave1',M1dep,M1ctd,M1pHcal);
   M1pH.lon = interp1(M1gps(:,1), M1gps(:,2), M1pH.time);
   M1pH.lat = interp1(M1gps(:,1), M1gps(:,3), M1pH.time);
  %CO2 %NOW WITH STANDARD?
   M1co2 = load_M1_CO2('m1-slave1',M1dep,M1ctd,M1co2cal);
   M1co2.lon = interp1(M1gps(:,1), M1gps(:,2), M1co2.time);
   M1co2.lat = interp1(M1gps(:,1), M1gps(:,3), M1co2.time);
  clear M1dep M1gps M1*cal;

%index M1 data within 4 km, 10-60 min
 tolSp = 4; %km
 %CTD
  [ia,ib,indBad] = getIndexNear(CTD1(:,1), CTD1(:,5), CTD1(:,6),...
    M1ctd.time, M1ctd.lon, M1ctd.lat, tolSp, 10/1440);
  CTD1(:,7:8) = NaN(size(CTD1,1),2); %T, S
  CTD1(ia,7:8) = [M1ctd.temp(ib(ia)) M1ctd.sal(ib(ia))];
  CTD1(indBad,7:8) = NaN;
 %O2
  [ia,ib,indBad] = getIndexNear(CTD1(:,1), CTD1(:,5), CTD1(:,6),...
    M1o2.time, M1o2.lon, M1o2.lat, 2, 10/1440);
  CTD1(:,9) = NaN(size(CTD1,1),1); %O2
  CTD1(ia,9) = M1o2.o2umolkg(ib(ia));
  CTD1(indBad,9) = NaN;
 clear tolSp ia ib indBad;

%------------%

%QC CTD1:

% (1) Time-series plot
% This is used to manually NaN data, for example, if there are intermittent
%  issues with the pump flow rate of the pH/O2 stream, or salinity
%  spikes not caught by the filter (below).
 figCTD1 = figure('Name','CTD1','Units','inches','Position',[0 0 11 8.5]);
 ha = tight_subplot(3,1,0.075,0.1,0.1);
 g = get(ha,'Position');
 set(ha,'Box','on','NextPlot','add');
 axes(ha(1));
   plot(CTD1(:,1),CTD1(:,2),'.-');
   ylabel(['[' char(186) 'C]']);
   title('Temperature');
   uicontrol('Units','normalized','Style','pushbutton','String','NaN',...
     'Position',[g{1}(1)+g{1}(3)-0.08 g{1}(2)+g{1}(4)+0.003 .08 .03],...
     'Callback','CTD1(:,2) = qcWG_NaNcb(CTD1(:,1),CTD1(:,2),ha(1));');
 axes(ha(2));
   plot(CTD1(:,1),CTD1(:,3),'.-');
   ylabel('');
   title('Salinity');
   uicontrol('Units','normalized','Style','pushbutton','String','NaN',...
     'Position',[g{2}(1)+g{2}(3)-0.08 g{2}(2)+g{2}(4)+0.003 .08 .03],...
     'Callback','CTD1(:,3) = qcWG_NaNcb(CTD1(:,1),CTD1(:,3),ha(2));');
 axes(ha(3));
   plot(CTD1(:,1),CTD1(:,4),'.-');
   ylabel(['[' char(181) 'mol kg^-^1]']);
   title('Oxygen');
   uicontrol('Units','normalized','Style','pushbutton','String','NaN',...
     'Position',[g{3}(1)+g{3}(3)-0.08 g{3}(2)+g{3}(4)+0.003 .08 .03],...
     'Callback','CTD1(:,4) = qcWG_NaNcb(CTD1(:,1),CTD1(:,4),ha(3));');
 set(ha,'XLim',[min(CTD1(:,1)) max(CTD1(:,1))] + [-1 1]*0.1);
 linkaxes(ha,'x');

% (2) Sliding variance filter on salinity
% These parameters tend to do a good job identifying spikes in salinity,
%  which occur in pretty much every deployment. I have been implementing
%  this as a rule for every WG mission. Additional spikes can be manually
%  removed in the CTD time-series plot.
 win = 100; %window
 nst = 5; %number of stdev's above median
 sm = slidingmed(CTD1(:,3), win);
 ss = slidingstdev(CTD1(:,3), win);
 fs = find(abs(CTD1(:,3) - sm) > nst*ss);
 clear win nst sm ss;
%check
 axes(ha(2));
 plot(CTD1(fs,1),CTD1(fs,3),'m.');
%NaN bad data
 CTD1(fs,3) = NaN;
 clear fs;

% (3) T vs S
% This is used to further identify bad salinity data by looking for
%  outliers in water-mass properties. Single-point outliers are often
%  easily identified here. This only 'flags' the outliers; you still
%  need to zoom-in and manually click the 'NaN' button in the time-series
%  plot to NaN the data.
 f = [];
 x = CTD1(:,3);
 y = CTD1(:,2);
 figTS1 = figure('Name','TS','Units','inches','Position',[0 0 11 8.5]);
 plot(x,y,'.');
 hold on;
%  plot(CTD(:,8),CTD(:,7),'g.'); %M1
 xlabel('S');
 ylabel(['T [' char(186) 'C]']);
 g = get(gca,'Position');
 uicontrol(figTS1,'Units','normalized','Style','pushbutton','String','FLAG',...
   'Position',[g(1)+g(3)-0.08 g(2)+g(4)+0.003 .08 .03],...
   'Callback',...
   ['gx=get(gca,''XLim'');' ...
    'gy=get(gca,''YLim'');' ...
    'f=[f; find(x>=gx(1) & x<=gx(2) & y>=gy(1) & y<=gy(2))];' ...
    'figure(figTS1); plot(x(f),y(f),''k.'');' ...
    'figure(figCTD1); axes(ha(2)); plot(CTD1(f,1),CTD1(f,3),''k.'');']);
 uiwait(figTS1);
 clear f x y g gx gy;

% (4) T vs O2
% This is used to identify bad oxygen data by looking for outliers in
%  water-mass properties. Note, according to Booth et al., O2 in MB is
%  basically never < 62 umol/kg (2.0 mg/l), and is rarely below 143 umol/kg.
%  This only 'flags' the outliers; you still need to zoom-in and manually
%  click the 'NaN' button in the time-series plot to NaN the data.
 f = [];
 x = CTD1(:,2);
 y = CTD1(:,4);
 figTO1 = figure('Name','TO','Units','inches','Position',[0 0 11 8.5]);
 plot(x,y,'.');
 hold on;
%  plot(CTD(:,7),CTD(:,9),'g.'); %M1
 xlabel(['T [' char(186) 'C]']);
 ylabel(['O2 [' char(181) 'mol kg^-^1]']);
 g = get(gca,'Position');
 uicontrol('Units','normalized','Style','pushbutton','String','FLAG',...
   'Position',[g(1)+g(3)-0.08 g(2)+g(4)+0.003 .08 .03],...
   'Callback',...
   ['gx=get(gca,''XLim'');' ...
    'gy=get(gca,''YLim'');' ...
    'f=[f; find(x>=gx(1) & x<=gx(2) & y>=gy(1) & y<=gy(2))];' ...
    'figure(figTO1); plot(x(f),y(f),''k.'');' ...
    'figure(figCTD1); axes(ha(3)); plot(CTD1(f,1),CTD1(f,4),''k.'');']);
 uiwait(figTO1);
 clear f x y g gx gy;

%NaN O2 data where S is NaN
 CTD1(isnan(CTD1(:,3)),4) = NaN;

%save QC'd .csv file
 time = (CTD1(:,1) - dn) * 86400*1000;
 fid = fopen([mydirQC 'CTD1.csv'],'w');
 fprintf(fid, ['Time[GMT/Unix*1000],temperature[C],salinity,' ...
   'oxygen[umol/kg]']);
 for n=1:size(CTD1,1)
   fprintf(fid, '\n%.0f,%.3f,%.3f,%.3f', [time(n) CTD1(n,2:4)]);
 end
 fclose(fid);
 clear time fid n;

close(figCTD1);
clear ha le figCTD1 figTS1 figTO1;

%QC CTD2:

% (1) Time-series plot
% This is used to manually NaN data, for example, if there are intermittent
%  issues with the pump flow rate of the pH/O2 stream, or salinity
%  spikes not caught by the filter (below).
 figCTD2 = figure('Name','CTD1','Units','inches','Position',[0 0 11 8.5]);
 ha = tight_subplot(3,1,0.075,0.1,0.1);
 g = get(ha,'Position');
 set(ha,'Box','on','NextPlot','add');
 axes(ha(1));
   plot(CTD2(:,1),CTD2(:,2),'.-');
   ylabel(['[' char(186) 'C]']);
   title('Temperature');
   uicontrol('Units','normalized','Style','pushbutton','String','NaN',...
     'Position',[g{1}(1)+g{1}(3)-0.08 g{1}(2)+g{1}(4)+0.003 .08 .03],...
     'Callback','CTD2(:,2) = qcWG_NaNcb(CTD2(:,1),CTD2(:,2),ha(1));');
 axes(ha(2));
   plot(CTD2(:,1),CTD2(:,3),'.-');
   ylabel('');
   title('Salinity');
   uicontrol('Units','normalized','Style','pushbutton','String','NaN',...
     'Position',[g{2}(1)+g{2}(3)-0.08 g{2}(2)+g{2}(4)+0.003 .08 .03],...
     'Callback','CTD2(:,3) = qcWG_NaNcb(CTD2(:,1),CTD2(:,3),ha(2));');
 axes(ha(3));
   plot(CTD2(:,1),CTD2(:,4),'.-');
   ylabel(['[' char(181) 'mol kg^-^1]']);
   title('Oxygen');
   uicontrol('Units','normalized','Style','pushbutton','String','NaN',...
     'Position',[g{3}(1)+g{3}(3)-0.08 g{3}(2)+g{3}(4)+0.003 .08 .03],...
     'Callback','CTD2(:,4) = qcWG_NaNcb(CTD2(:,1),CTD2(:,4),ha(3));');
 set(ha,'XLim',[min(CTD2(:,1)) max(CTD2(:,1))] + [-1 1]*0.1);
 linkaxes(ha,'x');

% (2) Sliding variance filter on salinity
% These parameters tend to do a good job identifying spikes in salinity,
%  which occur in pretty much every deployment. I have been implementing
%  this as a rule for every WG mission. Additional spikes can be manually
%  removed in the CTD time-series plot.
 win = 100; %window
 nst = 5; %number of stdev's above median
 sm = slidingmed(CTD2(:,3), win);
 ss = slidingstdev(CTD2(:,3), win);
 fs = find(abs(CTD2(:,3) - sm) > nst*ss);
 clear win nst sm ss;
%check
 axes(ha(2));
 plot(CTD2(fs,1),CTD2(fs,3),'m.');
%NaN bad data
 CTD2(fs,3) = NaN;
 clear fs;

% (3) T vs S
% This is used to further identify bad salinity data by looking for
%  outliers in water-mass properties. Single-point outliers are often
%  easily identified here. This only 'flags' the outliers; you still
%  need to zoom-in and manually click the 'NaN' button in the time-series
%  plot to NaN the data.
 f = [];
 x = CTD2(:,3);
 y = CTD2(:,2);
 figTS2 = figure('Name','TS','Units','inches','Position',[0 0 11 8.5]);
 plot(x,y,'.');
 hold on;
 xlabel('S');
 ylabel(['T [' char(186) 'C]']);
 g = get(gca,'Position');
 uicontrol(figTS2,'Units','normalized','Style','pushbutton','String','FLAG',...
   'Position',[g(1)+g(3)-0.08 g(2)+g(4)+0.003 .08 .03],...
   'Callback',...
   ['gx=get(gca,''XLim'');' ...
    'gy=get(gca,''YLim'');' ...
    'f=[f; find(x>=gx(1) & x<=gx(2) & y>=gy(1) & y<=gy(2))];' ...
    'figure(figTS2); plot(x(f),y(f),''k.'');' ...
    'figure(figCTD2); axes(ha(2)); plot(CTD2(f,1),CTD2(f,3),''k.'');']);
 uiwait(figTS2);
 clear f x y g gx gy;

% (4) T vs O2
% This is used to identify bad oxygen data by looking for outliers in
%  water-mass properties. Note, according to Booth et al., O2 in MB is
%  basically never < 62 umol/kg (2.0 mg/l), and is rarely below 143 umol/kg.
%  This only 'flags' the outliers; you still need to zoom-in and manually
%  click the 'NaN' button in the time-series plot to NaN the data.
 f = [];
 x = CTD2(:,2);
 y = CTD2(:,4);
 figTO2 = figure('Name','TO','Units','inches','Position',[0 0 11 8.5]);
 plot(x,y,'.');
 hold on;
%  plot(CTD(:,7),CTD(:,9),'g.'); %M1
 xlabel(['T [' char(186) 'C]']);
 ylabel(['O2 [' char(181) 'mol kg^-^1]']);
 g = get(gca,'Position');
 uicontrol('Units','normalized','Style','pushbutton','String','FLAG',...
   'Position',[g(1)+g(3)-0.08 g(2)+g(4)+0.003 .08 .03],...
   'Callback',...
   ['gx=get(gca,''XLim'');' ...
    'gy=get(gca,''YLim'');' ...
    'f=[f; find(x>=gx(1) & x<=gx(2) & y>=gy(1) & y<=gy(2))];' ...
    'figure(figTO2); plot(x(f),y(f),''k.'');' ...
    'figure(figCTD2); axes(ha(3)); plot(CTD2(f,1),CTD2(f,4),''k.'');']);
 uiwait(figTO2);
 clear f x y g gx gy;

%NaN O2 data where S is NaN
 CTD2(isnan(CTD2(:,3)),4) = NaN;

%save QC'd .csv file
 time = (CTD2(:,1) - dn) * 86400*1000;
 fid = fopen([mydirQC 'CTD2.csv'],'w');
 fprintf(fid, ['Time[GMT/Unix*1000],temperature[C],salinity,' ...
   'oxygen[umol/kg]']);
 for n=1:size(CTD2,1)
   fprintf(fid, '\n%.0f,%.3f,%.3f,%.3f', [time(n) CTD2(n,2:4)]);
 end
 fclose(fid);
 clear time fid n;

close(figCTD2);
clear ha le figCTD2 figTS2 figTO2;

%------------%

%QC Eco-Puck:

% (1) Time-series plot
% This is used to manually NaN data, for example, if the Eco-Puck sensor
%  became fouled or had barnacles attach to sensor body.
 figEP = figure('Name','EP','Units','inches','Position',[0 0 11 8.5]);
 ha = tight_subplot(3,1,0.075,0.1,0.1);
 g = get(ha,'Position');
 set(ha,'Box','on','NextPlot','add');
 axes(ha(1));
   plot(EP(:,1),EP(:,2),'.-');
   ylabel(['[' char(181) 'g L^-^1]']);
   title('Chlorophyll');
   uicontrol('Units','normalized','Style','pushbutton','String','NaN',...
     'Position',[g{1}(1)+g{1}(3)-0.08 g{1}(2)+g{1}(4)+0.003 .08 .03],...
     'Callback','EP(:,2) = qcWG_NaNcb(EP(:,1),EP(:,2),ha(1));');
 axes(ha(2));
   plot(EP(:,1),EP(:,3),'.-');
   ylabel('[m^-^1]');
   title('bb470');
   uicontrol('Units','normalized','Style','pushbutton','String','NaN',...
     'Position',[g{2}(1)+g{2}(3)-0.08 g{2}(2)+g{2}(4)+0.003 .08 .03],...
     'Callback','EP(:,3) = qcWG_NaNcb(EP(:,1),EP(:,3),ha(2));');
 axes(ha(3));
   plot(EP(:,1),EP(:,4),'.-');
   ylabel(['[m^-^1]']);
   title('bb650');
   uicontrol('Units','normalized','Style','pushbutton','String','NaN',...
     'Position',[g{3}(1)+g{3}(3)-0.08 g{3}(2)+g{3}(4)+0.003 .08 .03],...
     'Callback','EP(:,4) = qcWG_NaNcb(EP(:,1),EP(:,4),ha(3));');
 set(ha,'XLim',[min(EP(:,1)) max(EP(:,1))] + [-1 1]*0.1);
 linkaxes(ha,'x');

%save QC'd .csv file
 time = (EP(:,1) - dn) * 86400*1000;
 fid = fopen([mydirQC 'EcoPuck.csv'],'w');
 fprintf(fid, ['Time[GMT/Unix*1000],chlorophyll[ug/L],bb470[1/m],' ...
   'bb650[1/m]']);
 for n=1:size(EP,1)
   fprintf(fid, '\n%.0f,%.3f,%.5f,%.5f', [time(n) EP(n,2:4)]);
 end
 fclose(fid);
 clear time fid n;

close(figEP);
clear ha figEP g;

%------------%

%QC MET:

% (1) Time-series plot
% This is used to manually NaN data, for example, if the MET atm pressure
%  sensor started reporting bad data. Typical range for atm pressure is 
%  1000 - 1030 hPa (or mbar).
 figMET = figure('Name','MET','Units','inches','Position',[0 0 11 8.5]);
 ha = tight_subplot(2,1,0.075,0.2,0.1);
 g = get(ha,'Position');
 set(ha,'Box','on','NextPlot','add');
 axes(ha(1));
   plot(MET(:,1),MET(:,2),'.-');
%    plot(M1ctd.time,M1ctd.temp,'.-','Color',[.8 1 .8]);
%    plot(CTD(:,1),CTD(:,7),'.','Color',[0 .8 0],'MarkerSize',10);
%    le=legend('WG','M1');
%    set(le,'Color','none');
   ylabel(['[mbar]']);
   title('Atmospheric Pressure');
   uicontrol('Units','normalized','Style','pushbutton','String','NaN',...
     'Position',[g{1}(1)+g{1}(3)-0.08 g{1}(2)+g{1}(4)+0.003 .08 .03],...
     'Callback','MET(:,2) = qcWG_NaNcb(MET(:,1),MET(:,2),ha(1));');
 axes(ha(2));
   plot(MET(:,1),MET(:,3),'.-');
%    plot(M1ctd.time,M1ctd.sal,'.-','Color',[.8 1 .8]);
%    plot(CTD(:,1),CTD(:,8),'.','Color',[0 .8 0],'MarkerSize',10);
   ylabel(['[' char(186) 'C]']);
   title('Air Temperature');
   uicontrol('Units','normalized','Style','pushbutton','String','NaN',...
     'Position',[g{2}(1)+g{2}(3)-0.08 g{2}(2)+g{2}(4)+0.003 .08 .03],...
     'Callback','MET(:,3) = qcWG_NaNcb(MET(:,1),MET(:,3),ha(2));');
 set(ha,'XLim',[min(MET(:,1)) max(MET(:,1))] + [-1 1]*0.1);
 linkaxes(ha,'x');

%save QC'd .csv file
 time = (MET(:,1) - dn) * 86400*1000;
 fid = fopen([mydirQC 'MET.csv'],'w');
 fprintf(fid, ['Time[GMT/Unix*1000],airPress[hPa],airTemp[C]']);
 for n=1:size(MET,1)
   fprintf(fid, '\n%.0f,%.1f,%.1f', [time(n) MET(n,2:3)]);
 end
 fclose(fid);
 clear time fid n;

close(figMET);
clear ha figMET g;

%------------%

%QC METw:

% (1) Time-series plot
% This is used to manually NaN data, for example, if the MET wind
%  sensor started reporting bad data.
 figMETw = figure('Name','METw','Units','inches','Position',[0 0 11 8.5]);
 ha = tight_subplot(2,1,0.075,0.2,0.1);
 g = get(ha,'Position');
 set(ha,'Box','on','NextPlot','add');
 axes(ha(1));
   plot(METw(:,1),METw(:,2),'.');
%    plot(M1ctd.time,M1ctd.temp,'.-','Color',[.8 1 .8]);
%    plot(CTD(:,1),CTD(:,7),'.','Color',[0 .8 0],'MarkerSize',10);
%    le=legend('WG','M1');
%    set(le,'Color','none');
   ylabel(['[' char(181) 'True]']);
   title('Wind Direction');
   uicontrol('Units','normalized','Style','pushbutton','String','NaN',...
     'Position',[g{1}(1)+g{1}(3)-0.08 g{1}(2)+g{1}(4)+0.003 .08 .03],...
     'Callback','METw(:,2) = qcWG_NaNcb(METw(:,1),METw(:,2),ha(1));');
 axes(ha(2));
   plot(METw(:,1),METw(:,3),'.-');
%    plot(M1ctd.time,M1ctd.sal,'.-','Color',[.8 1 .8]);
%    plot(CTD(:,1),CTD(:,8),'.','Color',[0 .8 0],'MarkerSize',10);
   ylabel(['[m s^-^1]']);
   title('Wind Speed');
   uicontrol('Units','normalized','Style','pushbutton','String','NaN',...
     'Position',[g{2}(1)+g{2}(3)-0.08 g{2}(2)+g{2}(4)+0.003 .08 .03],...
     'Callback','METw(:,3) = qcWG_NaNcb(METw(:,1),METw(:,3),ha(2));');
 set(ha,'XLim',[min(METw(:,1)) max(METw(:,1))] + [-1 1]*0.1);
 linkaxes(ha,'x');

%save QC'd .csv file
 time = (METw(:,1) - dn) * 86400*1000;
 fid = fopen([mydirQC 'METwind.csv'],'w');
 fprintf(fid, ['Time[GMT/Unix*1000],windDir[True],windSpeed[m/s]']);
 for n=1:size(METw,1)
   fprintf(fid, '\n%.0f,%.1f,%.1f', [time(n) METw(n,2:3)]);
 end
 fclose(fid);
 clear time fid n;

close(figMETw);
clear ha figMETw g;

%------------%

%QC Position:

% (1) Time-series plot
% This is used to manually NaN data, for example, if the GPS started
%  reporting bad data.
% This has been updated to manually identify BOG Line data
 BogLine = zeros(size(Position(:,1)));
 figPos = figure('Name','Pos','Units','inches','Position',[0 0 11 8.5]);
 ha = tight_subplot(2,1,0.075,0.2,0.1);
 g = get(ha,'Position');
 set(ha,'Box','on','NextPlot','add');
 axes(ha(1));
   plot(Position(:,1),Position(:,2),'.-');
   ylabel(['[' char(186) 'E]']);
   title('Longitude');
   uicontrol('Units','normalized','Style','pushbutton','String','NaN',...
     'Position',[g{1}(1)+g{1}(3)-0.08 g{1}(2)+g{1}(4)+0.003 .08 .03],...
     'Callback','Position(:,2) = qcWG_NaNcb(Position(:,1),Position(:,2),ha(1));');
   uicontrol('Units','normalized','Style','pushbutton','String','BOG Line',...
     'Position',[g{1}(1)+g{1}(3)-0.2 g{1}(2)+g{1}(4)+0.003 .08 .03],...
     'Callback','BogLine = qcWG_BogLineCB(Position(:,1),Position(:,2),BogLine,ha(1));');
 axes(ha(2));
   plot(Position(:,1),Position(:,3),'.-');
   ylabel(['[' char(186) 'N]']);
   title('Latitude');
   uicontrol('Units','normalized','Style','pushbutton','String','NaN',...
     'Position',[g{2}(1)+g{2}(3)-0.08 g{2}(2)+g{2}(4)+0.003 .08 .03],...
     'Callback','Position(:,3) = qcWG_NaNcb(Position(:,1),Position(:,3),ha(2));');
 set(ha,'XLim',[min(Position(:,1)) max(Position(:,1))] + [-1 1]*0.1);
 linkaxes(ha,'x');

%save QC'd .csv file
 %Position
  time = (Position(:,1) - dn) * 86400*1000;
  fid = fopen([mydirQC 'Position.csv'],'w');
  fprintf(fid, ['Time[GMT/Unix*1000],longitude[E],latitude[N]']);
  for n=1:size(Position,1)
    fprintf(fid, '\n%.0f,%.5f,%.5f', [time(n) Position(n,2:3)]);
  end
  fclose(fid);
  clear time fid n;
 %BOG Line
  time = (Position(:,1) - dn) * 86400*1000;
  fid = fopen([mydirQC 'BogLine.csv'],'w');
  fprintf(fid, ['Time[GMT/Unix*1000],BogLine[N=0,Y=1]']);
  for n=1:size(Position,1)
    fprintf(fid, '\n%.0f,%.0f', [time(n) BogLine(n)]);
  end
  fclose(fid);
  clear time fid n;

%simply copy the Waypoint.csv file without any user-input
 copyfile([mydirPC 'Waypoint.csv'],[mydirQC 'Waypoint.csv']);

close(figPos);
clear ha figPos g;

%------------%

%Final Check:
%  qcWG_plotAll(Position,CTD1,CTD2,EP,MET,METw);
