function [noise,workdir] = fitnoise(varargin)
% FITNOISE Application M-file for fitnoise.fig
%    FIG = FITNOISE launch fitnoise GUI.
%    FITNOISE('callback_name', ...) invoke the named callback.

% Last Modified by GUIDE v2.0 12-Sep-2001 22:38:20

% Gets a noise file, fits a Gaussian to it, and returns the value of the noise
% and the directory the user chose, in case they want to go back to it later


% NB this is a daft kludge. Unless I use NLLF_gaussian outside an if-loop, it doesn't get compiled for standalone mode, and i don't seem to be able to get around this with a pragma
negloglikelihood = NLLF_gaussian(1,[1 2 3 4]);

if nargin ==1  % LAUNCH GUI
    
    
    % Open FIG-file  
    fig = openfig(mfilename,'reuse');
    % Generate a structure of handles to pass to callbacks, and store it. 
    handles = guihandles(fig);
    hand = varargin{1};
    handles.workdir = hand.workdir;
    handles.noise = hand.fitspecs.noise;
    handles.fitspecs = hand.fitspecs;
    guidata(fig, handles);

    % Populate the listbox
    load_listbox(handles.workdir,handles)
    
    % Wait for callbacks to run and window to be dismissed:
    uiwait(fig);
    
    % UIWAIT might have returned because the window was deleted using
    % the close box - in that case, don't bother deleting the window!
    if ~ishandle(fig)
        noise = NaN;
    else
        % retrieve the latest copy of the 'handles' struct, and return the answer.
        % Also, we need to delete the window.
        handles = guidata(fig);
        noise = handles.noise;
        workdir = handles.workdir;
        delete(fig);
    end

    

elseif ischar(varargin{1}) % INVOKE NAMED SUBFUNCTION OR CALLBACK

	try
		if (nargout)
			[varargout{1:nargout}] = feval(varargin{:}); % FEVAL switchyard
		else
			feval(varargin{:}); % FEVAL switchyard
		end
	catch
		disp(lasterr);
	end

end


%| ABOUT CALLBACKS:
%| GUIDE automatically appends subfunction prototypes to this file, and 
%| sets objects' callback properties to call them through the FEVAL 
%| switchyard above. This comment describes that mechanism.
%|
%| Each callback subfunction declaration has the following form:
%| <SUBFUNCTION_NAME>(H, EVENTDATA, HANDLES, VARARGIN)
%|
%| The subfunction name is composed using the object's Tag and the 
%| callback type separated by '_', e.g. 'slider2_Callback',
%| 'figure1_CloseRequestFcn', 'axis1_ButtondownFcn'.
%|
%| H is the callback object's handle (obtained using GCBO).
%|
%| EVENTDATA is empty, but reserved for future use.
%|
%| HANDLES is a structure containing handles of components in GUI using
%| tags as fieldnames, e.g. handles.figure1, handles.slider2. This
%| structure is created at GUI startup using GUIHANDLES and stored in
%| the figure's application data using GUIDATA. A copy of the structure
%| is passed to each callback.  You can store additional information in
%| this structure at GUI startup, and you can change the structure
%| during callbacks.  Call guidata(h, handles) after changing your
%| copy to replace the stored original so that subsequent callbacks see
%| the updates. Type "help guihandles" and "help guidata" for more
%| information.
%|
%| VARARGIN contains any extra arguments you have passed to the
%| callback. Specify the extra arguments by editing the callback
%| property in the inspector. By default, GUIDE sets the property to:
%| <MFILENAME>('<SUBFUNCTION_NAME>', gcbo, [], guidata(gcbo))
%| Add any extra arguments after the last argument, before the final
%| closing parenthesis.


% --------------------------------------------------------------------
function varargout = edit1_Callback(h, eventdata, handles, varargin)




% --------------------------------------------------------------------
function varargout = edit2_Callback(h, eventdata, handles, varargin)



% ------------------------------------------------------------
% Callback for list box - open .fig with guide, otherwise use open
% ------------------------------------------------------------
function varargout = datafile_Callback(h, eventdata, handles, varargin)
if strcmp(get(handles.figure1,'SelectionType'),'open')
    index_selected = get(handles.datafile,'Value');
    file_list = get(handles.datafile,'String');	
    filename = file_list{index_selected};
    if  handles.is_dir(handles.sorted_index(index_selected))
        homedir = pwd;
        cd (handles.workdir)
        workdir = filename;
        load_listbox(workdir,handles)
        cd(homedir)
    else
        try
            ReadInData([handles.workdir '\' filename],handles)
        catch
            errordlg(lasterr,'Some problem with data','modal')
        end
    end
end
% ------------------------------------------------------------
% Read the current directory and sort the names
% ------------------------------------------------------------
function load_listbox(dir_path,handles)
handles.homedir=pwd
cd (dir_path);
disp('where looking now')
handles.workdir=pwd;
dir_struct = dir(pwd);
[sorted_names,sorted_index] = sortrows({dir_struct.name}');
handles.file_names = sorted_names;
handles.is_dir = [dir_struct.isdir];
handles.sorted_index = [sorted_index];
guidata(handles.figure1,handles)
set(handles.datafile,'String',handles.file_names,'Value',1)
set(handles.workdirbox,'String',pwd)
cd(handles.homedir);

% --------------------------------------------------------------------
function varargout = Exit1_Callback(h, eventdata, handles, varargin)
confirmandexit




%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function ReadInData(noisefile,handles)
% Read in data from data file.
[path,name,ext,ver] = fileparts(noisefile);
resultsdir = path;
noisefile= [name ext];
% Catch an error involving an invalid file:
fid = fopen([resultsdir '\' noisefile],'r');
if fid == -1
    errordlg(['Cannot open the file ' resultsdir '\' noisefile '. Try another file.'])
    return
else
    noisedata = fscanf(fid,'%f');
    ndata = length(noisedata);
    % NB some of my functions need data to be a row not a column vector. Next few lines ensure this:
    [tmp1,tmp2] = size(noisedata);
    if tmp1>tmp2, noisedata = noisedata', end
    
    if ndata>1 
        %if the file could be opened and contained at least 1 data point, accept this data
        
        if get(handles.radiobutton2,'value') == get(handles.radiobutton2,'Max')
            % then the second button is checked, meaning fit offset as well as SD
            initialparams = [0 100];
            [params,NLLF,exitstatus] = fminsearch('NLLF_gaussian',initialparams,[],noisedata);
            offset = params(1);
            noise = params(2);
        else
            % then the 1st button must be checked, meaning set offset to zero
            offset = 0;
            initialparams = 100;
            [params,NLLF,exitstatus] = fminsearch('NLLF_gaussian',initialparams,[],noisedata);
            noise = params;
        end
        % NLLF = -log(L) of the fit.
        % exitstatus says whether it worked or not
        if (exitstatus<=0)
            disp(' ')
            errordlg(['Program was unable to fit the noise data in ' noisefile ' with a Gaussian. '])
            return
        else
            figure('name','Noise fitted with Gaussian');
            [y,x]=hist(noisedata,handles.fitspecs.numbins);
            % Normalise:
            y=y/trapz(x,y);
            bar(x,y,'b')
            set(gca,'ytick',[])
            hold on
            
            mn = min(noisedata); mx = max(noisedata);
            v=[0: (mx-mn)/1000: mx-mn] + mn;
            tmpPDF = exp(-(v-offset).^2./noise^2./2) / sqrt(2*pi)/noise;
            plot(v,tmpPDF,'r','linewidth',handles.fitspecs.lw)
            title(['Noise from file ' noisefile])
            xlabel(['Fitted with a Gaussian of SD ' num2str(noise) '; offset = ' num2str(offset)])            
            
            % Find a suitable range to display model PDF over
            axis tight
            tmp = get(gca,'ylim');
            mxy = tmp(2);
            set(gca,'ylim',[0 1.1*mxy],'ytick',[])
            
            % keep the noise
            handles.noise = noise;
            guidata(handles.figure1, handles);
            uiresume(handles.figure1);
            
        end
        
    else
        errordlg(['The file ' resultsdir '\' noisefile ' does not contain valid data. Enter another file.'])
        return
    end
end





% --------------------------------------------------------------------
function varargout = radiobutton1_Callback(h, eventdata, handles, varargin)
if get(h,'value')==get(h,'Min')
    set(handles.radiobutton2,'value',get(handles.radiobutton2,'Max'));
elseif get(h,'value')==get(h,'Max')
    set(handles.radiobutton2,'value',get(handles.radiobutton2,'Min'));
end



% --------------------------------------------------------------------
function varargout = radiobutton2_Callback(h, eventdata, handles, varargin)
if get(h,'value')==get(h,'Min')
    set(handles.radiobutton1,'value',get(handles.radiobutton2,'Max'));
elseif get(h,'value')==get(h,'Max')
    set(handles.radiobutton1,'value',get(handles.radiobutton2,'Min'));
end

% --------------------------------------------------------------------
function varargout = cancelbutton_Callback(h, eventdata, handles, varargin)
uiresume(handles.figure1);

