%	Generates single-trace plots of the following GNSS navigation data:
%       - position (lat,lon,alt)
%       - position standard deviation (NED)
%       - solution status

function generic_plot_computed_gnss_pos( action,     ...
                                         data_path,  ...
                                         kernel,     ...
                                         start_time, ...
                                         fignum,     ...
                                         prefix,     ...
                                         fig_caption)

persistent num_plots;
persistent figure_params  % Array holding a structure for each instance call of this routine

thismfile=mfilename;

switch action
    
    case 'start'
        
        figure_params(fignum).h_fig_listbox = -1;

        %------------------------------------------------------------------
        % Load the data

        filename = [data_path prefix kernel '.out'];
        
        if test_file(filename) == 0                	% External function
            return;
        end
          
        data = load_gnss_data(filename);        	% Private function below
        
        %------------------------------------------------------------------
        % Plot the data

        % Get figure and Y-axis label captions

        y_label_caption = set_y_label_captions;     % Private function below
        
        % Bring up new figure window and set its properties
        
        fig_title = [fig_caption ' for '];
        new_plot_figure(fignum,fig_title,kernel);   % External function
        
        num_plots = 16;
        figure_params(fignum).current_plot_num = 1;
        figure_params(fignum).used_fig_captions ={'empty'};  % Allocate value as cell type
 
        % Due to plot axis labelling limitation and the number of significant digits in GPS time
        % subtract the start time and plot seconds from start - start_time is given in x-axis label

        if (start_time < 0.0)
            start_time = data.time(1);
        end;

        for i=1:num_plots
            figure_params(fignum).axis_handle(i) = axes;        
            switch i
                case 1
                    figure_params(fignum).plot_handle(i) = plot(data.time-start_time,data.lat,'k');
                case 2
                    figure_params(fignum).plot_handle(i) = plot(data.time-start_time,data.lon,'k');
                case 3
                    figure_params(fignum).plot_handle(i) = plot(data.time-start_time,data.alt,'k');   
                case 4
                    figure_params(fignum).plot_handle(i) = plot(data.time-start_time,data.N_pos_sigma,'k');
                case 5
                    figure_params(fignum).plot_handle(i) = plot(data.time-start_time,data.E_pos_sigma,'k');
                case 6
                    figure_params(fignum).plot_handle(i) = plot(data.time-start_time,data.D_pos_sigma,'k');
                case 7
                    figure_params(fignum).plot_handle(i) = plot(data.time-start_time,data.N_vel,'k');
                case 8
                    figure_params(fignum).plot_handle(i) = plot(data.time-start_time,data.E_vel,'k');
                case 9
                    figure_params(fignum).plot_handle(i) = plot(data.time-start_time,data.D_vel,'k');
                case 10
                    figure_params(fignum).plot_handle(i) = plot(data.time-start_time,data.N_vel_sigma,'k');
                case 11
                    figure_params(fignum).plot_handle(i) = plot(data.time-start_time,data.E_vel_sigma,'k');
                case 12
                    figure_params(fignum).plot_handle(i) = plot(data.time-start_time,data.D_vel_sigma,'k');
                case 13
                    figure_params(fignum).plot_handle(i) = plot(data.time-start_time,data.PDOP,'k');
                case 14
                    figure_params(fignum).plot_handle(i) = plot(data.time-start_time,data.HDOP,'k');
                case 15
                    figure_params(fignum).plot_handle(i) = plot(data.time-start_time,data.VDOP,'k');
                case 16
                    figure_params(fignum).plot_handle(i) = plot(data.time-start_time,data.status,'k');
            end
            
            if i > 1
                set(figure_params(fignum).axis_handle(i),'visible','off')
                set(figure_params(fignum).plot_handle(i),'visible','off')
            end
            
            title(fig_caption);
            ylabel(y_label_caption(i));
            x_label_caption = sprintf('Time in seconds starting at %i',start_time);
            xlabel(x_label_caption);
            axis('tight')
            
            % Adjust ylim for status plot
            
            if i==num_plots
                set(gca,'ylim',[min(data.status)-1 max(data.status)+1]);
            end
            
            figure_params(fignum).used_fig_captions(i) = y_label_caption(i);
            
        end % for i=1:num_plots
        
        axes(figure_params(fignum).axis_handle(figure_params(fignum).current_plot_num));
        
        % Create buttons
        
        hleft = uicontrol('style','push','pos',[10 50 20 20],'TooltipString','Cycle left',...
            'callback',[ thismfile '(''left'');' ],'fontname','symbol','string',char(172));
        hright = uicontrol('style','push','pos',[10 30 20 20],'TooltipString','Cycle right',...
            'callback',[ thismfile '(''right'');' ],'fontname','symbol','string',char(174));
        hlist = uicontrol('style','push','pos',[10 10 40 20],'TooltipString','Plot selection list',...
            'callback',[ thismfile '(''list'');' ],'string','List');

        % Only need the one zoom -need to be after buttons for Matlab 7
        
        zoom on

    case 'left'

        fignum = str2num(get(gcf,'Tag'));
        figure_params(fignum).current_plot_num = figure_params(fignum).current_plot_num - 1;
        if figure_params(fignum).current_plot_num < 1
            figure_params(fignum).current_plot_num = num_plots;   % Wrap to last plot
        end
        
        for i=1:num_plots
            set(figure_params(fignum).axis_handle(i),'visible','off')
            set(figure_params(fignum).plot_handle(i),'visible','off')
        end
        set(figure_params(fignum).axis_handle(figure_params(fignum).current_plot_num),'visible','on')
        set(figure_params(fignum).plot_handle(figure_params(fignum).current_plot_num),'visible','on')
        axes(figure_params(fignum).axis_handle(figure_params(fignum).current_plot_num))

    case 'right'

        fignum = str2num(get(gcf,'Tag'));
        figure_params(fignum).current_plot_num = figure_params(fignum).current_plot_num + 1;
        if figure_params(fignum).current_plot_num > num_plots
            figure_params(fignum).current_plot_num = 1;           % Wrap to first plot
        end
        
        for i=1:num_plots
            set(figure_params(fignum).axis_handle(i),'visible','off')
            set(figure_params(fignum).plot_handle(i),'visible','off')
        end
        set(figure_params(fignum).axis_handle(figure_params(fignum).current_plot_num),'visible','on')
        set(figure_params(fignum).plot_handle(figure_params(fignum).current_plot_num),'visible','on')
        axes(figure_params(fignum).axis_handle(figure_params(fignum).current_plot_num))

    case 'list'

        fignum = str2num(get(gcf,'Tag'));
        h_fig = gcf;
        
        if ishandle(figure_params(fignum).h_fig_listbox) == 0
            figure_params(fignum).h_fig_listbox = figure('name',['Plot Selection List'],'NumberTitle', 'off','Menu','none');     % ' char(figure_caption(i))]);
            set(figure_params(fignum).h_fig_listbox,'units','characters');
            set(gcf,'Tag',num2str(fignum));

            %get location of parent window
            set(h_fig,'units','characters');
            apos=get(h_fig,'pos');
            
            %set vertical position
            top = apos(2) + apos(4);  % bottom+ height
            new_height = num_plots + 7;
            new_bottom = top - new_height;
            apos(2) = new_bottom;
            apos(4) = new_height;
            
            %set horiz position
            new_left = apos(1) + 0.25*apos(3); % left +25% of width
            new_width = 40;
            apos(1) = new_left;
            apos(3) = new_width;
            set(figure_params(fignum).h_fig_listbox,'pos',apos);
    
            figure_params(fignum).h_listbox = uicontrol('style','listbox','units','normalized','pos',[.1 .05 .8 .8],'TooltipString','List box',...
              'callback',[ thismfile '(''listbox'');' ]);
            set(figure_params(fignum).h_listbox,'value',figure_params(fignum).current_plot_num);
            set(figure_params(fignum).h_listbox,'string',figure_params(fignum).used_fig_captions);
            
            h_OK = uicontrol('style','push','units','normalized','pos',[.15 .87 .25 .10],'TooltipString','OK',...
                'callback',[ thismfile '(''ListBox_OK'');' ],'string','OK');
            h_Cancel = uicontrol('style','push','units','normalized','pos',[.55 .87 .25 .10],'TooltipString','Cancel',...
                'callback',[ thismfile '(''ListBox_Cancel'');' ],'string','Cancel');
            figure_params(fignum).new_plot_num = 0;
        end

    case 'listbox'

        fignum = str2num(get(gcf,'Tag'));
        selectiontype = get(gcbf,'SelectionType');
        
        if selectiontype(1)=='o'
            figure_params(fignum).new_plot_num = get(figure_params(fignum).h_listbox,'value');
            figure_params(fignum).current_plot_num = ...
                update_plot_1( figure_params(fignum).new_plot_num, ...  % External function
                               figure_params(fignum).plot_handle,  ...
                               figure_params(fignum).axis_handle,  ...
                               num_plots);
            close(figure_params(fignum).h_fig_listbox);
            figure_params(fignum).h_fig_listbox = -1;
        end    
        
        if selectiontype(1)=='n'
            figure_params(fignum).new_plot_num = get(figure_params(fignum).h_listbox,'value');
        end    

    case 'ListBox_OK'

        fignum = str2num(get(gcf,'Tag'));
        if figure_params(fignum).new_plot_num ~= 0
            figure_params(fignum).current_plot_num = ...
                update_plot_1( figure_params(fignum).new_plot_num, ...  % External function
                               figure_params(fignum).plot_handle,  ...
                               figure_params(fignum).axis_handle,  ...
                               num_plots );
        end
        close(figure_params(fignum).h_fig_listbox);
        figure_params(fignum).h_fig_listbox = -1;
           
    case 'ListBox_Cancel'

        fignum = str2num(get(gcf,'Tag'));
        close(figure_params(fignum).h_fig_listbox);
        figure_params(fignum).h_fig_listbox = -1;
        
end %switch

%--------------------------------------------------------------------------
%
function data = load_gnss_data(filename)

% Data structure (92 bytes)
        
% double time;
% double pos[3];
% float  pos_sd[3];
% float  vel[3];
% float  vel_sd[3];
% float  dop[3];
% char   receiver;
% char   status;
% float  corr_latency;
% float  vel_latency;
% char   pos_valid;
% char   vel_valid;
           
record_size = 92;
size_of_double = 8;
size_of_float = 4;
size_of_uint8 = 1;

num_data_pts = inf;

fid = fopen(filename,'rb');

% Load elements of each record independently using SKIP on the fread statement

offset = 0;
[data.time, count] = fread(fid,num_data_pts,'double',record_size-size_of_double);

offset = offset + size_of_double;
fseek(fid,offset,'bof');
[data.lat, count] = fread(fid,num_data_pts,'double',record_size-size_of_double);

offset = offset + size_of_double;
fseek(fid,offset,'bof');
[data.lon, count] = fread(fid,num_data_pts,'double',record_size-size_of_double);

offset = offset + size_of_double;
fseek(fid,offset,'bof');
[data.alt, count] = fread(fid,num_data_pts,'double',record_size-size_of_double);

offset = offset + size_of_double;
fseek(fid,offset,'bof');
[data.N_pos_sigma, count] = fread(fid,num_data_pts,'float32',record_size-size_of_float);

offset = offset + size_of_float;
fseek(fid,offset,'bof');
[data.E_pos_sigma, count] = fread(fid,num_data_pts,'float32',record_size-size_of_float);

offset = offset + size_of_float;
fseek(fid,offset,'bof');
[data.D_pos_sigma, count] = fread(fid,num_data_pts,'float32',record_size-size_of_float);

offset = offset + size_of_float;
fseek(fid,offset,'bof');
[data.N_vel, count] = fread(fid,num_data_pts,'float32',record_size-size_of_float);

offset = offset + size_of_float;
fseek(fid,offset,'bof');
[data.E_vel, count] = fread(fid,num_data_pts,'float32',record_size-size_of_float);

offset = offset + size_of_float;
fseek(fid,offset,'bof');
[data.D_vel, count] = fread(fid,num_data_pts,'float32',record_size-size_of_float);

offset = offset + size_of_float;
fseek(fid,offset,'bof');
[data.N_vel_sigma, count] = fread(fid,num_data_pts,'float32',record_size-size_of_float);

offset = offset + size_of_float;
fseek(fid,offset,'bof');
[data.E_vel_sigma, count] = fread(fid,num_data_pts,'float32',record_size-size_of_float);

offset = offset + size_of_float;
fseek(fid,offset,'bof');
[data.D_vel_sigma, count] = fread(fid,num_data_pts,'float32',record_size-size_of_float);

offset = offset + size_of_float;
fseek(fid,offset,'bof');
[data.PDOP, count] = fread(fid,num_data_pts,'float32',record_size-size_of_float);

offset = offset + size_of_float;
fseek(fid,offset,'bof');
[data.HDOP, count] = fread(fid,num_data_pts,'float32',record_size-size_of_float);

offset = offset + size_of_float;
fseek(fid,offset,'bof');
[data.VDOP, count] = fread(fid,num_data_pts,'float32',record_size-size_of_float);

% Load status element of each record independently using SKIP on the fread statement

offset = offset + size_of_float + size_of_uint8;
fseek(fid,offset,'bof');
[data.status, count] = fread(fid,num_data_pts,'uint8',record_size-size_of_uint8);

fclose(fid);

%--------------------------------------------------------------------------
%
function y_label_caption = set_y_label_captions

% Use cells to handle variable length strings

y_label_caption( 1) = {'Latitude (degrees)'};
y_label_caption( 2) = {'Longitude (degrees)'};
y_label_caption( 3) = {'Altitude (meters)'};
y_label_caption( 4) = {'North position standard deviation (meters)'};
y_label_caption( 5) = {'East position standard deviation (meters)'};
y_label_caption( 6) = {'Down position standard deviation (meters)'};
y_label_caption( 7) = {'North velocity (meters/second)'};
y_label_caption( 8) = {'East velocity (meters/second)'};
y_label_caption( 9) = {'Down velocity (meters/second)'};
y_label_caption(10) = {'North velocity standard deviation (meters/second)'};
y_label_caption(11) = {'East velocity standard deviation (meters/second)'};
y_label_caption(12) = {'Down velocity standard deviation (meters/second)'};
y_label_caption(13) = {'PDOP'};
y_label_caption(14) = {'HDOP'};
y_label_caption(15) = {'VDOP'};
y_label_caption(16) = {'Solution status (0=FIXED RTK, 8=CA, 10=NO SOLUTION)'};
