% PROCESSNOAA
% ===========
%
% Version
% -------
% 1.1.2
%
% Description
% -----------
% PROCESSNOAA is a Graphical User Interface (GUI) that extracts, processes, and calculates rainfall and wind direction and speed variables from National Oceanic and            % Atmospheric Administration (NOAA) data files.  Barometric pressure data are also extracted.  The NOAA data files are local climatological data collected at airports that     % contain measurements of rainfall, wind speed, wind direction, and barometric pressure.  PROCESSNOAA allows users to view plots and tables of processed rainfall, wind speed, % and wind direction data.  In addition, users can merge field measurements of E.coli with NOAA data files, and save processed data in a format ready for direct import into   % Virtual Beach.
%
% A detailed description of this program and its use is described in the following USGS Report:
%
%	 Francy, D.S., Brady, A.M.G., Carvin, R.B., Corsi, S.R., Fuller, L.M., Harrison, J.H., Hayhurst, B.A., Lant, J., Nevers, M.B., Terrio, P.J., and Zimmerman, T.M., 2013, %    Developing and implementing predictive models for estimating recreational water quality at Great Lakes beaches: U.S. Geological Survey Scientific Investigations Report %    2013–5166, in press.
%
% The source code can be found at:
%	 ftp://ftpext.usgs.gov/pub/er/ky/louisville/jglant/processnoaa/processnoaa_version-1.1.2.zip
%
% PROCESSNOAA was written in MATLAB using release 2010a. PROCESSNOAA ran on a Dell Inc. Precision Workstation T7500 x64-based PC using Microsoft Windows 7 Enterprise.  
%
% Requirements
% ------------
% To use PROCESSNOAA, a free MATLAB Component Runtime Library needs to be installed on the computer that will run PROCESSNOAA.  The MATLAB Runtime Library is available for    % download from the USGS Office of Surface Water:
%
%	http://hydroacoustics.usgs.gov/software/MCR1.shtml
%
% Author
% ------
% Jeremiah Lant
% Hydrologist
% USGS Kentucky Water Science Center 
% jlant@usgs.gov
%
% Date of last revison
% --------------------
% March 26, 2013
%
% DISCLAIMER and NOTICE
% ---------------------
% Please refer to the USGS Software User Rights Notice (http://water.usgs.gov/software/help/notice/) for complete use, copyright, and distribution information. The USGS provides no warranty, expressed or implied, as to the correctness of the furnished software or the suitability for any purpose. The software has been tested, but as with any complex software, there could be undetected errors. Users who find errors are requested to report them to the USGS.
%
% References to non-USGS products, trade names, and (or) services are provided for information purposes only and do not constitute endorsement or warranty, express or implied, by the USGS, U.S. Department of Interior, or U.S. Government, as to their suitability, content, usefulness, functioning, completeness, or accuracy.
%
% 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.


function varargout = PROCESSNOAA(varargin)
% PROCESSNOAA M-file for PROCESSNOAA.fig
%      PROCESSNOAA, by itself, creates a new PROCESSNOAA or raises the existing
%      singleton*.
%
%      H = PROCESSNOAA returns the handle to a new PROCESSNOAA or the handle to
%      the existing singleton*.
%
%      PROCESSNOAA('CALLBACK',hObject,eventData,handles,...) calls the local
%      function named CALLBACK in PROCESSNOAA.M with the given input arguments.
%
%      PROCESSNOAA('Property','Value',...) creates a new PROCESSNOAA or raises the
%      existing singleton*.  Starting from the left, property value pairs are
%      applied to the GUI before PROCESSNOAA_OpeningFcn gets called.  An
%      unrecognized property name or invalid value makes property application
%      stop.  All inputs are passed to PROCESSNOAA_OpeningFcn via varargin.
%
%      *See GUI Options on GUIDE's Tools menu.  Choose "GUI allows only one
%      instance to run (singleton)".
%
% See also: GUIDE, GUIDATA, GUIHANDLES

% Edit the above text to modify the response to help PROCESSNOAA

% Last Modified by GUIDE v2.5 26-Mar-2013 16:01:15

% Begin initialization code - DO NOT EDIT
gui_Singleton = 1;
gui_State = struct('gui_Name',       mfilename, ...
                   'gui_Singleton',  gui_Singleton, ...
                   'gui_OpeningFcn', @PROCESSNOAA_OpeningFcn, ...
                   'gui_OutputFcn',  @PROCESSNOAA_OutputFcn, ...
                   'gui_LayoutFcn',  [] , ...
                   'gui_Callback',   []);
if nargin && ischar(varargin{1})
    gui_State.gui_Callback = str2func(varargin{1});
end

if nargout
    [varargout{1:nargout}] = gui_mainfcn(gui_State, varargin{:});
else
    gui_mainfcn(gui_State, varargin{:});
end
% End initialization code - DO NOT EDIT


% --- Executes just before PROCESSNOAA is made visible.
function PROCESSNOAA_OpeningFcn(hObject, eventdata, handles, varargin)
% This function has no output args, see OutputFcn.
% hObject    handle to figure
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
% varargin   command line arguments to PROCESSNOAA (see VARARGIN)

% Choose default command line output for PROCESSNOAA
handles.output = hObject;

% --------------- Initialize GUI variables and interface -----------------
% Display name of the GUI
handles.version='PROCESSNOAA Version 1.1';
set(handles.figure1,'Name',handles.version);

% Disable all menu and popup options so user can not click on them without 
% loading a data file first
% Save Menu
set(handles.saveHourly,'Enable','off');
set(handles.saveDaily,'Enable','off');
% Options Menu
set(handles.view,'Enable','off');
set(handles.precipFrequency,'Enable','off');
set(handles.windSpFreq,'Enable','off');
set(handles.windDirFreq,'Enable','off');
set(handles.ecoliFreq,'Enable','off');
set(handles.mergeEcoli,'Enable','off');
% Tables
set(handles.tableDaily,'Enable','off');
set(handles.tableHourly,'Enable','off');
% Timeseries Popup Menu
set(handles.popupTimeSeries,'Enable','off');
set(handles.popupEcoli,'Enable','off');
handles.dailyColName = {'Year';'Month';'Day';'Hour';'Minute';'Day of Year';...
                'Wind Speed Inst';'Wind Direction Inst';...
                'Airport Rain D-1';'Airport Rain D-2';...
                'Airport Rain D-3';'Airport Rain 48 Weighted';...
                'Airport Rain 72 Weighted';'Barometric Pressure Inst'};
set(handles.tableDaily,'ColumnName',handles.dailyColName);

% Create figure windows for histogram (frequency) plots of Precipitation,
% Wind Speed, and Wind Direction
handles.f1 = figure('MenuBar','none','NumberTitle','off','Visible','off');
handles.f2 = figure('MenuBar','none','NumberTitle','off','Visible','off');
handles.f3 = figure('MenuBar','none','NumberTitle','off','Visible','off');
handles.f4 = figure('MenuBar','none','NumberTitle','off','Visible','off');

% Create a matrix to hold all the data with ecoli data
handles.combinedDataMatrix = [];

% Update handles structure
guidata(hObject, handles);

% UIWAIT makes NOAAData wait for user response (see UIRESUME)
% uiwait(handles.figure1);


% --- Outputs from this function are returned to the command line.
function varargout = PROCESSNOAA_OutputFcn(hObject, eventdata, handles) 
% varargout  cell array for returning output args (see VARARGOUT);
% hObject    handle to figure
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Get default command line output from handles structure
varargout{1} = handles.output;


%=========================================================================
%                         MENU OPTIONS
%=========================================================================

%                          OPEN MENU
% --------------------------------------------------------------------
function file_Callback(hObject, eventdata, handles)
% hObject    handle to file (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% --------------------------------------------------------------------
function openFiles_Callback(hObject, eventdata, handles)
% hObject    handle to openFiles (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Clear gui handles if user had previous data open
handles = clear_gui(handles);

%-------------------------- Load Data ----------------------------------
% Open window for user to select all the NOAA *.txt files of interest
% fileName will contain all the files that the user selected
[fileName, pathName] = uigetfile('*.txt','Pick NOAA text file(s)','MultiSelect','on');

% If user clicks "Cancel", uigetfile returns 0.
if isequal(fileName,0)
   return
end

% If user chooses only one file, change it from a character data type to a
% cell array
if ischar(fileName)
    fileName = {fileName};
end

% Initialize variables
N = length(fileName);
dataFile = cell(N,1);
headerMonth = cell(N,1);
headerYear = cell(N,1);
% dataMatrixHourly will hold all of the hourly data
dataMatrixHourly = [];

% Loop through files and process one at a time
for k = 1:N
   
   % Concatenate pathName and fileName
   fullName = strcat(pathName,fileName(k));
   
   % Open the file
   fid = fopen(fullName{1});
   
   % Make sure that the file is proper
   dataCheck = textscan(fid,'%s',1,'Delimiter','');
   if strcmp(dataCheck{1},'Hourly Obs ') || strcmp(dataCheck{1},'Hourly Obs')
       
       % Read Header
       dataHeader = textscan(fid,'%s',5,'Delimiter',',');
       % Assign variables to header.
       headerMonthYear = cell2mat(dataHeader{1}(1));
       headerMonth{k} = headerMonthYear(13:14);
       headerYear{k} = headerMonthYear(16:end);
       
       headerStation = cell2mat(dataHeader{1}(2));
       headerStation = headerStation(19:end);
       
       headerLat = cell2mat(dataHeader{1}(3));
       headerLat = headerLat(6:end);
       
       headerLon = cell2mat(dataHeader{1}(4));
       headerLon = headerLon(6:end);
       
       headerElev = cell2mat(dataHeader{1}(5));
       headerElev = headerElev(7:end);
       
       % Read units line
       dataFormat = '%s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s';
       dataUnits = textscan(fid,dataFormat,1,'Delimiter',',','CollectOutput',1);
       % Assign variables to units of interest
       unitDate = cell2mat(dataUnits{1}(2));
       unitTime = cell2mat(dataUnits{1}(3));
       unitWindSpeed = cell2mat(dataUnits{1}(25));
       unitWindDir = cell2mat(dataUnits{1}(27));
       unitPrecip = cell2mat(dataUnits{1}(41));
       
       % Read rest of data
       dataFile{k} = textscan(fid,dataFormat,'Delimiter',',');
       
       % Extract relevant data and convert the data into numeric arrays
       date = dataFile{k}{2};
       time = dataFile{k}{3};
       windsp = dataFile{k}{25};
       winddir = dataFile{k}{27};
       precip = dataFile{k}{41};
       
       % Barometric Pressure: Station Pressure
       pressure = dataFile{k}{31};
       pressure = str2double(pressure);
       
       %---------------------- ORGANIZE DATA ------------------------------
       %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
       % DATE
       year = zeros(length(date),1);
       month = zeros(length(date),1);
       day = zeros(length(date),1);
       for i = 1:length(date)
           year(i) = str2double(date{i}(1:4));
           month(i) = str2double(date{i}(5:6));
           day(i) = str2double(date{i}(7:end));
       end
       
       %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
       % TIME
       hr = zeros(length(time),1);
       min = zeros(length(time),1);
       sec =  zeros(length(time),1);
       for i = 1:length(time)
           % Assign hrs and minutes
           hr(i) = str2double(time{i}(1:2));
           min(i) = str2double(time{i}(3:4));
       end
       
       % Find autominute using histogram approach - finds the minute that occurs the most
       [cnts bins] = hist(min,1:1:59);
       a = [cnts' bins'];
       % Sort descending order and pick top 5 minutes
       a = sortrows(a,-1);
       a = a(1:5,:);
       automin = a(:,2);
       % Pick only those minutes occuring between the 50th - 59th minute 
       automin = automin(automin>=50);
       
       index = [];
       for i = 1:length(automin)
          j = min == automin(i);
          index = [index j];
       end
       % Sum along rows to get all indices occuring at the 5 different
       % autominutes
       index = sum(index,2);
       idx = find(index==1);
      
       %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
       % WIND DIRECTION and WIND SPEED
       windsp = str2double(windsp);
       winddir = str2double(winddir);
       
       %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
       % PRECIPITATION
       % Replace 'T' (trace character) in precip array with '0.005'
       for i = 1:length(precip)
           if precip{i} == 'T'
               precip{i} = '0.005';
           end
       end
       precip = str2double(precip);
       
       %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
       % DATA MATRIX
       % Put data into a matrix
       data = [year month day hr min sec windsp winddir precip pressure];

       % Eliminate those indices that occur at the same hour, meaning pick
       % only one of the values that occur in that hour
       data = data(idx,:);
       d = diff(data(:,4));
       idxtest = find(d==0);
       
       for i = 1:length(idxtest)-1
          val1 = data(idxtest(i),4);
          val2 = data(idxtest(i)+1,4);
          if val1 == automin(1)
              data(idxtest(i)+1,:) = [];
          elseif val2 == automin(1)
              data(idxtest(i),:) = [];
          end
       end
       
       %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
       % FIX NaN
       % Call fixNan function to fix all the NaN ('VR') values in winddir column
       data(:,8) = fixNan(data(:,8));
       
       % Call fixNan function to fix all the NaN ('VR') values in windsp column
       data(:,7) = fixNan(data(:,7));
       
       % Call fixNan function to fix all the NaN ('VR') values in pressure column
       data(:,end) = fixNan(data(:,end));
       
       %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
       % CREATE MATRIX with PERFECT TIMESTEP
       % Find start date and end date
       startDate = data(1,1:6);
       endDate = data(end,1:6);
       
       % Create serial numbers for dates
       startDate = datenum(startDate);
       endDate = datenum(endDate);
       
       % Create a perfect 1 hour time series from startDate to endDate
       % Add a little bit (0.001) to get endDate in the array
       timestep = datenum([0 0 0 1 0 0]);
       timePerfect = [startDate:timestep:endDate+.001]';
       
       % Create a matrix to hold all the data with same number of rows as the
       % timePerfect array and the same number of columns as the data matrix
       dataHourly = nan(size(timePerfect,1), size(data,2));
       dataHourly(:,1:6) = datevec(timePerfect);
       % Take care of rounding in the conversion from serial date to vector date
       dataHourly(:,6) = round(dataHourly(:,6));
       
       %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
       % ALGORITHM for inserting matching data between dataMatrixOrig and the
       % dataMatrixHourly.
       
       % Orig -> serial number
       dateSerial = datenum(data(:,1:6));
       % Take difference in dates (multiplying by 24 gives 1 hour)
       dateDiff = diff(dateSerial)*24;
       % Do a cumulative sum of the difference vector and add 1 to get the index
       % of the dataMatrix containing recorded data
       dateCumSum = cumsum([0;dateDiff]);
       idx = round(dateCumSum)+1;
       
       % Assign original data into the matrix with the proper time step. The
       % dataMatrixHourly will now show NaN in the winddir and windsp where there are
       % gaps (missing data) in the orginal data.
       dataHourly(idx,:) = data;

       dataMatrixHourly = [dataMatrixHourly; dataHourly];
       
       % Close the file
       fclose(fid);
       
   else
       errordlg('Improper input file(s). Please select proper NOAA *.txt file.')
       return
   end
end

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Sort by month
dataMatrixHourly = sortrows(dataMatrixHourly,2);
% Sort by year
dataMatrixHourly = sortrows(dataMatrixHourly,1);

% STRIP UNNECESSARY DATA 
% **Note: There is not a full antecedent day on the first day.
% Find the first instance of the 7th hour on the first day and delete the 
% the data up to and including the 7th hour of the first day (This data 
% will include hours from midnight on the first day to the 7th hour on the 
% first day.  Do the same thing for the last instance of the 7th hour on
% the last day. 
idxHr7 = find(dataMatrixHourly(:,4) == 7);
startIdx = idxHr7(1);
endIdx = idxHr7(end);

% Strip unnecessary data from beginning and end
dataMatrixHourly(endIdx+1:end,:) = [];
dataMatrixHourly(1:startIdx,:) = [];

% Find the values at the 7th hour again after trimming ends of matrix
% idxHr7 will consist of indices in multiples of 24 hrs; [24 48 72 96 ...]
idxHr7 = find(dataMatrixHourly(:,4) == 7);

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% GET DATA OF INTEREST
% Note: data = [year month day hr min sec windsp winddir precip pressure]
%                 1    2    3  4   5   6    7       8      9      10
% Get instantaneous wind speed and wind direction at the 7th hour
windspInstant = dataMatrixHourly(idxHr7,7);
winddirInstant = dataMatrixHourly(idxHr7,8);

% Get the date and time at the 7th hour
yearInstant = dataMatrixHourly(idxHr7,1);
monthInstant = dataMatrixHourly(idxHr7,2);
dayInstant = dataMatrixHourly(idxHr7,3);
hrInstant = dataMatrixHourly(idxHr7,4);
minInstant = dataMatrixHourly(idxHr7,5);

% Get the pressure at the 7th hour
pressureInstant = dataMatrixHourly(idxHr7,10);

% Calculate the daily antecedent sum for precip;
precipSum = nan(size(idxHr7,1),1);
for i = 1:length(precipSum)
    precipSum(i) = nansum(dataMatrixHourly(idxHr7(i)-23:idxHr7(i),9));
end

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% ADDITIONAL CALCULATIONS

% Calculate Day of Year
% Note: doy = date2doy(inDate); -> where inDate is a proper argument for
% datenum
doy = [];
yrs = unique(yearInstant(:,1));
for i = 1:length(yrs)
    idx = find(yearInstant == yrs(i));
    dateVector = [yearInstant(idx),monthInstant(idx),dayInstant(idx)];
    doyTemp = date2doy(dateVector);
    doy = [doy; doyTemp];
end

% Calculate 24 Hr and 48 Hr Lag
precip24HrLag = [NaN;precipSum;NaN;NaN];
precip48HrLag = [NaN;NaN;precipSum;NaN];

% Add 3 additional NaN's to the end of each data array for the daily table
% This ensures that all vectors are the same length as the lagged vectors.
yearInstant = [yearInstant; NaN;NaN;NaN];
monthInstant = [monthInstant; NaN;NaN;NaN];
dayInstant = [dayInstant; NaN;NaN;NaN];
hrInstant = [hrInstant; NaN;NaN;NaN];
minInstant = [minInstant; NaN;NaN;NaN];
doy = [doy; NaN;NaN;NaN];
precipSum = [precipSum; NaN;NaN;NaN];
windspInstant = [windspInstant; NaN;NaN;NaN];
winddirInstant = [winddirInstant; NaN;NaN;NaN];
pressureInstant = [pressureInstant; NaN;NaN;NaN];

% Calculate Weighted Precipitation
precip48HrW = 2*(precipSum) + precip24HrLag;
precip72HrW = 3*(precipSum) + 2*(precip24HrLag) + precip48HrLag;

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% ORGANIZE DATA and UPDATE HANDLES

% Put all the antecdent data of interest together 
dataMatrixDaily = [yearInstant monthInstant dayInstant hrInstant minInstant ...
                    doy windspInstant winddirInstant ...
                    precipSum precip24HrLag precip48HrLag ...
                    precip48HrW precip72HrW pressureInstant];
         
% Delete the seconds column from Hourly matrix.
% This column only contains zeros which is used to get serial number dates
dataMatrixHourly(:,6) = [];

% Set the text boxes in the Info and Tables Panel
set(handles.txtBoxNOAASite,'String',headerStation);
set(handles.txtBoxLat,'String',headerLat);
set(handles.txtBoxLon,'String',headerLon);
set(handles.txtBoxElev,'String',headerElev);
% Month string
monthString = sortrows(headerMonth);
monthString = unique(monthString);
monthString = sprintf('%s ', monthString{:});
set(handles.txtBoxMonth,'String',monthString);
% Year string
yearString = sortrows(headerYear);
yearString = unique(yearString);
yearString = sprintf('%s ', yearString{:});
set(handles.txtBoxYear,'String',yearString);

% Enable all menu and popup options so user can click on them
% Save Menu
set(handles.saveHourly,'Enable','on');
set(handles.saveDaily,'Enable','on');
% Options Menu
set(handles.view,'Enable','on');
set(handles.precipFrequency,'Enable','on');
set(handles.windSpFreq,'Enable','on');
set(handles.windDirFreq,'Enable','on');
set(handles.mergeEcoli,'Enable','on');
% Tables
set(handles.tableDaily,'Enable','on');
set(handles.tableHourly,'Enable','on');
% Timeseries Popup Menu
set(handles.popupTimeSeries,'Enable','on');

% Assign handles to data of interest and pathName
handles.dataMatrixHourly = dataMatrixHourly;
handles.dataMatrixDaily = dataMatrixDaily;
handles.pathName = pathName;

% Set the data into the tables (without the valid number)
set(handles.tableDaily,'Data',handles.dataMatrixDaily);
set(handles.tableHourly,'Data',handles.dataMatrixHourly);

% Update handles structure
guidata(hObject, handles);

% Call plot_TimeSeries function and plot day of year vs. antecedent precip
plot_TimeSeries(handles,1)

% UIWAIT makes PROCESSNOAA wait for user response (see UIRESUME)
% uiwait(handles.figure1);


%                          SAVE MENU
% --------------------------------------------------------------------
function save_Callback(hObject, eventdata, handles)
% hObject    handle to save (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)


% --------------------------------------------------------------------
function saveHourly_Callback(hObject, eventdata, handles)
% hObject    handle to saveHourly (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Delete previous output file if it exists
if exist([handles.pathName 'HourlyData.xls'],'file') == 2
    delete([handles.pathName 'HourlyData.xls'])
end

% Get the column headers and data from the table
colHeaders = get(handles.tableHourly,'ColumnName');
colHeaders = colHeaders(5:end);
colHeaders(1) = {'Date'};
tableData = get(handles.tableHourly,'Data');
% Format the date
d = zeros(length(tableData),6);
d(:,1:5) = tableData(:,1:5);
date = datenum(d);
date = datestr(date,'mm/dd/yyyy HH:MM');
date = cellstr(date);
% Write data to excel file called DailyData and put in same directory as
% the input data
xlswrite([handles.pathName 'HourlyData.xls'],colHeaders(:)','Sheet1','A1');
xlswrite([handles.pathName 'HourlyData.xls'],date, 'Sheet1','A2');
xlswrite([handles.pathName 'HourlyData.xls'],tableData(:,6:end), 'Sheet1','B2');

% Update handles structure
guidata(hObject, handles);

% --------------------------------------------------------------------
function saveDaily_Callback(hObject, eventdata, handles)
% hObject    handle to saveDaily (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Delete previous output file if it exists
if exist([handles.pathName 'DailyData.xls'],'file') == 2
    delete([handles.pathName 'DailyData.xls'])
end
% Column names needed to look like the following for the *.xls file
colNameVB = {'Date';'DayofYear'; 'WindSpInst_mph';'WindDirInst_deg';...
                'AirportRainD-1';'AirportRainD-2';'AirportRainD-3';...
                'AirportRain48W_in';'AirportRain72W_in';'BarPressureInst_inhg'};
            
if isempty(handles.combinedDataMatrix)
    % Get the column headers and data from the table
    tableData = get(handles.tableDaily,'Data');
    % Do not keep the 3 NaN values at the end of the rows
    tableData = tableData(1:end-3,:);
    
    % Format the date
    d = zeros(length(tableData),6);
    d(:,1:5) = tableData(:,1:5);
    date = datenum(d);
    date = datestr(date,'mm/dd/yyyy');
    date = cellstr(date);
    
    % Write data to excel file called DailyData and put in same directory as
    % the input data
    xlswrite([handles.pathName 'DailyData.xls'],colNameVB','Sheet1','A1');
    xlswrite([handles.pathName 'DailyData.xls'],date, 'Sheet1','A2');
    xlswrite([handles.pathName 'DailyData.xls'],tableData(:,6:end), 'Sheet1','B2');

else
    % Get the column headers and data from the table
    colHeaders = get(handles.tableDaily,'ColumnName');
    % Find index of 'Day'; should always be 3rd column
    ind_day = find(strcmp(colHeaders,'Day'));
    % Find index of 'Day of Year'
    ind_doy = find(strcmp(colHeaders,'Day of Year'));
    % Ecoli headers
    ecoliHeaders = colHeaders(ind_day + 1:ind_doy - 1);
    % Create the column names for the xls file
    colNames_xls = [colNameVB(1); ecoliHeaders; colNameVB(2:end)];
    % Get the table data
    tableData = get(handles.tableDaily,'Data');
    % Do not include the 'Year', 'Month', 'Day' columns
    tableData_xls = tableData(:,ind_day + 1:end);

    % Format the date
    d = zeros(length(tableData),6);
    d(:,1:3) = tableData(:,1:3);
    date = datenum(d);
    date = datestr(date,'mm/dd/yyyy');
    date = cellstr(date);
    
    % Write data to excel file called DailyData and put in same directory as
    % the input data
    xlswrite([handles.pathName 'DailyData.xls'],colNames_xls','Sheet1','A1');
    xlswrite([handles.pathName 'DailyData.xls'],date, 'Sheet1','A2');
    xlswrite([handles.pathName 'DailyData.xls'],tableData_xls, 'Sheet1','B2');
end
% Update handles structure
guidata(hObject, handles);


%                         OPTIONS MENU
% --------------------------------------------------------------------
function options_Callback(hObject, eventdata, handles)
% hObject    handle to options (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)


% --------------------------------------------------------------------
function mergeEcoli_Callback(hObject, eventdata, handles)
% hObject    handle to mergeEcoli (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Open window for user to select a e.coli (*.xls) file that contains dates
% and corresponding e.coli data.  Merge the dates in the e.coli data file
% with the dates from the NOAA data
[fileName, pathName] = uigetfile('*.xls','Pick an E.coli file');

% If user clicks "Cancel", uigetfile returns 0.
if isequal(fileName,0)
   return
end

% Concatenate pathName and fileName
ecoliFile = strcat(pathName,fileName);
[num,txt,raw] = xlsread(ecoliFile);

% Get dates from string array called txt
txtDate = txt(2:end,1);
ecoliDate = datenum(txtDate,'mm/dd/yyyy');
ecoliDate = datevec(ecoliDate);

% Put e.coli dates and data into a matrix
ecoliMatrix = [ecoliDate num];

% Trim ecoliMatrix to only have dates with e.coli data
ecoliMatrix = ecoliMatrix(~isnan(ecoliMatrix(:,7)),:);

% Merge NOAA data with ecoli data
dataMatrixDaily = handles.dataMatrixDaily;

% Combine all data 
combinedDataMatrix = [];
for i = 1:length(dataMatrixDaily)
    for j = 1:length(ecoliMatrix)
        if dataMatrixDaily(i,1:3) == ecoliMatrix(j,1:3)
            matchData = [ecoliMatrix(j,:) dataMatrixDaily(i,6:end)];
            combinedDataMatrix = [combinedDataMatrix; matchData];
        end
    end
end

if ~isempty(combinedDataMatrix)
    
    % Delete the columns 4-6 (hr,min,sec)
    combinedDataMatrix(:,4:6) = [];
    
    % Set the finalDataMatrix to the "Daily Table"
    dailyColName = get(handles.tableDaily,'ColumnName');
    dailyColName = dailyColName';
    % Organize the column names
    dateColName = dailyColName(1:3);
    dailyColName = dailyColName(6:end);
    ecoliColName = txt(1,2:end);
    colName = [dateColName ecoliColName dailyColName];
    set(handles.tableDaily,'ColumnName',colName);
    set(handles.tableDaily,'Data', combinedDataMatrix);
    
    % Assign handle to the combinedDataMatrix which has the ecoli data
    handles.combinedDataMatrix = combinedDataMatrix;
        
    % Update handles structure
    guidata(hObject, handles);
    
    % Do not allow user to choose another e.coli file
    set(handles.mergeEcoli,'Enable','off');
    
    % Turn on popup menu for ecoli and turn off some other features
    set(handles.popupEcoli,'Enable','on');
    set(handles.view,'Enable','on');
    set(handles.ecoliFreq,'Enable','on');
    set(handles.popupTimeSeries,'Enable','on');
    
    % Plot e.coli vs. antecedent precip
    plot_Ecoli(handles,1)
   
else
    errordlg('The dates in the E.coli data do not correspond with the dates in the NOAA data.');
    return   
end


% --------------------------------------------------------------------
function view_Callback(hObject, eventdata, handles)
% hObject    handle to view (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% --------------------------------------------------------------------
function precipFrequency_Callback(hObject, eventdata, handles)
% hObject    handle to precipFrequency (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Create a histogram of precipitation
if isempty(handles.combinedDataMatrix)
    
    dataMatrixDaily = handles.dataMatrixDaily;
    
    if ~ishandle(handles.f1)
        handles.f1 = figure('MenuBar','none','NumberTitle','off','Visible','off');
    end
    % Proper column (PrecipSum = Airport Rain D-1) is 5 places from the end
    figure(handles.f1);
    x = 0:0.1:max(dataMatrixDaily(:,end-5));
    hist(dataMatrixDaily(:,end-5),x);
    xlabel('Airport Rain D-1')
    ylabel('Counts')
    title('Frequency Plot')
    set(handles.f1, 'Visible','on');
else
    combinedDataMatrix = handles.combinedDataMatrix;
    
    if ~ishandle(handles.f1)
        handles.f1 = figure('MenuBar','none','NumberTitle','off','Visible','off');
    end
    
    figure(handles.f1);
    x = 0:0.1:max(combinedDataMatrix(:,end-5));
    hist(combinedDataMatrix(:,end-5),x);
    xlabel('Airport Rain D-1')
    ylabel('Counts')
    title('Frequency Plot with Merged E.coli Data')
    set(handles.f1, 'Visible','on');
end

% --------------------------------------------------------------------
function windSpFreq_Callback(hObject, eventdata, handles)
% hObject    handle to windSpFreq (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Create a histogram of wind speed
if isempty(handles.combinedDataMatrix)
    
    dataMatrixDaily = handles.dataMatrixDaily;
    
    if ~ishandle(handles.f2)
        handles.f2 = figure('MenuBar','none','NumberTitle','off','Visible','off');
    end
    
    figure(handles.f2);
    x = 0:1:max(dataMatrixDaily(:,end-7));
    hist(dataMatrixDaily(:,end-7),x);
    xlabel('Wind Speed Inst')
    ylabel('Counts')
    title('Frequency Plot')
    set(handles.f2, 'Visible','on');
else
    combinedDataMatrix = handles.combinedDataMatrix;
    
    if ~ishandle(handles.f1)
        handles.f2 = figure('MenuBar','none','NumberTitle','off','Visible','off');
    end
    
    figure(handles.f2);
    x = 0:1:max(combinedDataMatrix(:,end-7));
    hist(combinedDataMatrix(:,end-7),x);
    xlabel('Wind Speed Inst')
    ylabel('Counts')
    title('Frequency Plot with Merged E.coli Data')
    set(handles.f2, 'Visible','on');
end

% --------------------------------------------------------------------
function windDirFreq_Callback(hObject, eventdata, handles)
% hObject    handle to windDirFreq (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Create a histogram of wind direction
if isempty(handles.combinedDataMatrix)
    
    dataMatrixDaily = handles.dataMatrixDaily;
    
    if ~ishandle(handles.f3)
        handles.f3 = figure('MenuBar','none','NumberTitle','off','Visible','off');
    end
    
    figure(handles.f3);
    x = 0:30:360;
    hist(dataMatrixDaily(:,end-6),x);
    xlabel('Wind Direction Inst')
    ylabel('Counts')
    title('Frequency Plot')
    set(handles.f3, 'Visible','on');
else
    combinedDataMatrix = handles.combinedDataMatrix;
    
    if ~ishandle(handles.f3)
        handles.f1 = figure('MenuBar','none','NumberTitle','off','Visible','off');
    end
    
    figure(handles.f3);
     x = 0:30:360;
    hist(combinedDataMatrix(:,end-6),x);
    xlabel('Wind Direction Inst')
    ylabel('Counts')
    title('Frequency Plot with Merged E.coli Data')
    set(handles.f3, 'Visible','on');
end

% --------------------------------------------------------------------
function ecoliFreq_Callback(hObject, eventdata, handles)
% hObject    handle to ecoliFreq (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Create a histogram of ecoli
if ~isempty(handles.combinedDataMatrix);
    
    combinedDataMatrix = handles.combinedDataMatrix;
    
    if ~ishandle(handles.f4)
        handles.f4 = figure('MenuBar','none','NumberTitle','off','Visible','off');
    end
    
    ecoli = combinedDataMatrix(:,4);
    ecoli = log10(ecoli);
    figure(handles.f4);
    x = 0:0.1:max(ecoli);
    [cnts bins]=hist(ecoli,x);
    hist(ecoli,x);
    hold on
    p1 = plot([2.37 2.37],[0 max(cnts)+1],'r','LineWidth',2);
    xlabel('Log10(E.coli)');
    ylabel('Counts');
    title('Frequency Plot');
    legend(p1,'E.coli Threshold (2.37)');
    set(handles.f4, 'Visible','on');
end



%                          EXIT MENU
% --------------------------------------------------------------------
function exit_Callback(hObject, eventdata, handles)
% hObject    handle to exit (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% --------------------------------------------------------------------
function exitProgram_Callback(hObject, eventdata, handles)
% hObject    handle to exitProgram (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

close all

%=========================================================================
%                    POPUP MENU FOR TIME SERIES PLOT
%=========================================================================
% --- Executes during object creation, after setting all properties.
function popupTimeSeries_CreateFcn(hObject, eventdata, handles)
% hObject    handle to popupTimeSeries (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    empty - handles not created until after all CreateFcns called

% Hint: popupmenu controls usually have a white background on Windows.
%       See ISPC and COMPUTER.
if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor','white');
end

% --- Executes on selection change in popupTimeSeries.
function popupTimeSeries_Callback(hObject, eventdata, handles)
% hObject    handle to popupTimeSeries (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Hints: contents = cellstr(get(hObject,'String')) returns popupTimeSeries contents as cell array
%        contents{get(hObject,'Value')} returns selected item from
%        popupTimeSeries

% Get the selected option
switch get(handles.popupTimeSeries,'Value')
    case 1
        val = 1;
        plot_TimeSeries(handles,val);
    case 2
        val = 2;
        plot_TimeSeries(handles,val);
    case 3
        val = 3;
        plot_TimeSeries(handles,val);
    otherwise
end

% --- Executes during object creation, after setting all properties.
function popupEcoli_CreateFcn(hObject, eventdata, handles)
% hObject    handle to popupEcoli (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    empty - handles not created until after all CreateFcns called

% Hint: popupmenu controls usually have a white background on Windows.
%       See ISPC and COMPUTER.
if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor','white');
end

% --- Executes on selection change in popupEcoli.
function popupEcoli_Callback(hObject, eventdata, handles)
% hObject    handle to popupEcoli (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Hints: contents = cellstr(get(hObject,'String')) returns popupEcoli contents as cell array
%        contents{get(hObject,'Value')} returns selected item from popupEcoli

% Get the selected option
switch get(handles.popupEcoli,'Value')
    case 1
        val = 1;
        plot_Ecoli(handles,val);
    case 2
        val = 2;
        plot_Ecoli(handles,val);
    case 3
        val = 3;
        plot_Ecoli(handles,val);
    otherwise
end


%=========================================================================
%                     FUNCTION - PLOT TIME SERIES
%=========================================================================
function plot_TimeSeries(handles, val)
% Plot a time series of precipitation, wind speed, and wind direction
%
% Parameters:
%   handles: handles structure containing all data
%	val: integer representing which plot to make 
%		 val = 1 -> Day of Year vs. Antecedent Precipiation
%		 val = 2 -> Day of Year vs. Instantaneous Wind Speed
%		 val = 3 -> Day of Year vs. Instantaneous Wind Direction
% Return:
%   none

% Allow for time series plotting even when ecoli data is added
if isempty(handles.combinedDataMatrix)
    % Assign local variables
    dataMatrixDaily = handles.dataMatrixDaily;
else
    dataMatrixDaily = handles.combinedDataMatrix;
end

% Reset the plot and use the proper axes
cla(handles.axesTimeSeries,'reset');
axes(handles.axesTimeSeries)

% Get the yrs from dataMatrixDaily and make matrices to hold data for
% plotting
yrs = unique(dataMatrixDaily(:,1));
yrs = yrs(~isnan(yrs));
legendItems = cell(length(yrs),1);
p = nan(5,1);

% Plot Day of Year vs. Antecedent Precipiation
if val == 1
    % Only allow for a maximum of 5 years of data to be plotted together
    colorBar = ['g','r','b','y','k'];
    
    for i = 1:length(yrs)
        dataTemp = dataMatrixDaily(dataMatrixDaily(:,1)==yrs(i),:);
        dateVector = [dataTemp(:,1),dataTemp(:,2),dataTemp(:,3)];
        doyTemp = date2doy(dateVector);
        precipTemp = dataTemp(:,end-5);
        hold on
        grid on
        p(i) = plot(doyTemp,precipTemp,'-ko','LineWidth',1,'MarkerFaceColor',colorBar(i));
        legendItems{i} = num2str(yrs(i));
    end
    
    plots = [];
    legendString = [];
    for i = 1:length(yrs)
        plots = [plots p(i)];
        legendString = [legendString legendItems(i)];
    end
    legend(plots,legendString)
    % Labels
    xlabel('Day of Year');
    ylabel('Airport Rain D-1');
end

% Plot Day of Year vs. Instantaneous Wind Speed
if val == 2
    % Only allow for a maximum of 5 years of data to be plotted together
    colorBar = ['y','m','g','r','b'];
    
    for i = 1:length(yrs)
        dataTemp = dataMatrixDaily(dataMatrixDaily(:,1)==yrs(i),:);
        dateVector = [dataTemp(:,1),dataTemp(:,2),dataTemp(:,3)];
        doyTemp = date2doy(dateVector);
        windspIn = dataTemp(:,end-7);
        hold on
        grid on
        p(i) = plot(doyTemp,windspIn,'-ko','LineWidth',1,'MarkerFaceColor',colorBar(i));
        legendItems{i} = num2str(yrs(i));
    end
    
    plots = [];
    legendString = [];
    for i = 1:length(yrs)
        plots = [plots p(i)];
        legendString = [legendString legendItems(i)];
    end
    % Legend
    legend(plots,legendString)
    % Labels
    xlabel('Day of Year');
    ylabel('Wind Speed Inst');
end

% Plot Day of Year vs. Instantaneous Wind Direction
if val == 3
    % Only allow for a maximum of 5 years of data to be plotted together
    colorBar = ['m','g','r','b','y'];
    
    for i = 1:length(yrs)
        dataTemp = dataMatrixDaily(dataMatrixDaily(:,1)==yrs(i),:);
        dateVector = [dataTemp(:,1),dataTemp(:,2),dataTemp(:,3)];
        doyTemp = date2doy(dateVector);
        winddirIn = dataTemp(:,end-6);
        hold on
        grid on
        p(i) = plot(doyTemp,winddirIn,'-ko','LineWidth',1,'MarkerFaceColor',colorBar(i));
        legendItems{i} = num2str(yrs(i));
    end
    
    plots = [];
    legendString = [];
    for i = 1:length(yrs)
        plots = [plots p(i)];
        legendString = [legendString legendItems(i)];
    end
    % Legend
    legend(plots,legendString)
    % Labels
    xlabel('Day of Year');
    ylabel('Wind Direction Inst');
end


%=========================================================================
%                     FUNCTION - PLOT ECOLI
%=========================================================================
function plot_Ecoli(handles, val)
% Plot ecoli versus precipitation, wind speed, and wind direction
%
% Parameters:
%   handles: handles structure containing all data
%	val: integer representing which plot to make 
%		 val = 1 -> E.coli vs. Antecedent Precipitation
%		 val = 2 -> E.coli vs. Wind Speed
%		 val = 3 -> E.coli vs. Wind Direction
% Return:
%   none

% Assign local variables
combinedDataMatrix = handles.combinedDataMatrix;

% Reset the plot and use the proper axes
cla(handles.axesTimeSeries,'reset');
axes(handles.axesTimeSeries)

% Get ecoli, precip, and wind data
ecoli = combinedDataMatrix(:,4);
ecoli = log10(ecoli);
precip_ecoli = combinedDataMatrix(:,end-5);
windsp_ecoli = combinedDataMatrix(:,end-7);
winddir_ecoli = combinedDataMatrix(:,end-6);

% Ecoli threshold of 2.37
threshold = 2.37;

% Plot E.coli vs. Antecedent Precipitation, Wind Speed, and Wind Direction
if val == 1
    p1 = plot(precip_ecoli, ecoli,'b*');
    hold on
    p2 = plot([0 max(precip_ecoli) + 1],[threshold threshold],'r','LineWidth',2);
    xlabel('Airport Rain D-1');
    ylabel('Log10(E.coli)');  
    legend(p2,'E.coli Threshold (2.37)');
   
elseif val == 2
    p1 = plot(windsp_ecoli, ecoli,'g*');
    hold on
    p2 = plot([0 max(windsp_ecoli) + 1],[threshold threshold],'r','LineWidth',2);
    xlabel('Wind Speed Inst');
    ylabel('Log10(E.coli)');  
    legend(p2,'E.coli Threshold (2.37)');
    
elseif val == 3
    p1 = plot(winddir_ecoli, ecoli,'k*');
    hold on
    p2 = plot([0 360],[threshold threshold],'r','LineWidth',2);
    xlabel('Wind Direction Inst');
    ylabel('Log10(E.coli)');
    legend(p2,'E.coli Threshold (2.37)');
end


%=========================================================================
%                     FUNCTION - CLEAR_GUI
%=========================================================================
function handles=clear_gui(handles)
% Clear all the data in the GUI.
%
% Parameters:
%   handles: handles structure containing all data
%
% Return:
%   none

% Clear data and tables
handles.dataMatrixHourly = [];
handles.dataMatrixDaily = [];
handles.combinedDataMatrix = [];
set(handles.tableHourly,'Enable','off');
set(handles.tableDaily,'Enable','off');
set(handles.tableDaily,'ColumnName',handles.dailyColName);
set(handles.saveHourly,'Enable','off');
set(handles.saveDaily,'Enable','off');
set(handles.popupTimeSeries,'Enable','off');
set(handles.popupEcoli,'Enable','off');
set(handles.ecoliFreq,'Enable','off');
set(handles.view,'Enable','off');
set(handles.mergeEcoli,'Enable','off');

% Clear plot
cla(handles.axesTimeSeries);

%=========================================================================
%                     FUNCTION - FIX NAN VALUES 
%=========================================================================
function [x] = fixNan(x)
% Replace 'NaN' values in wind direction data with the average
% of the previous non-NAN value and the next non-NAN value.
%
% Parameters:
%   x: array of data that may contain NAN values
%
% Return:
%   x: array of data without NAN values

% Fix NAN values
idx = find(~isnan(x));
k = 0;
for j = 1:length(x)
    if isnan(x(j))
        if j == 1
            x(j) = x(idx(1));
            k = k + 1;
        elseif j == length(x)
            x(j) = x(idx(end));
        else
            if 0 <= x(idx(k)) && x(idx(k)) <= 90 && ...
               270 <= x(idx(k+1)) && x(idx(k+1)) <= 360 ...
               || 270 <= x(idx(k)) && x(idx(k)) <= 360 && ...
               0 <= x(idx(k+1)) && x(idx(k+1)) <= 90  
           
               x(j) = 180 + (x(idx(k)) + x(idx(k+1)))/2;
                
                if x(j) > 360
                   x(j) = x(j) - 360; 
                end
            else
                x(j) = (x(idx(k)) + x(idx(k+1)))/2;
            end
        end
    else
        k = k + 1;
    end
end

%=========================================================================
%                     FUNCTION - COMPUTE DAY OF YEAR
%=========================================================================
function dayOfYear = date2doy(inDate) 
% Calculate the day of the year 1-365
%
% Parameters:
%   inDate: array of dates as proper "DateString" or "DateVector" to be used 
%   with Matlab's datenum function 
%
% Return:
%   dayOfYear: integer value of day of the year

inDate = datenum(inDate);
year = str2num(datestr(inDate,'yyyy'));
prevYear = datenum(year - 1, 12,31);
dayOfYear = inDate - prevYear;

% --- Executes when selected cell(s) is changed in tableDaily.
function tableDaily_CellSelectionCallback(hObject, eventdata, handles)
% hObject    handle to tableDaily (see GCBO)
% eventdata  structure with the following fields (see UITABLE)
%	Indices: row and column indices of the cell(s) currently selecteds
% handles    structure with handles and user data (see GUIDATA)
