% SHOWANGULARIM - Displays image of angular data
%
% For angular data to be rendered correctly it is important that the data values
% are respected so that data values are correctly assigned to specific entries
% in a cyclic colour map.  The assignment of values to colours also depends on
% whether the data is cyclic over pi, or 2*pi.  
%
% In contrast, default display methods typically do not respect data values
% directly and can perform inappropriate offsetting and normalisation of the
% angular data before display and rendering with a colour map.
%
% The rendering of the angular data with a specified colour map can be modulated
% as a function of an associated image amplitude.  This allows the colour map
% encoding of the angular information to be modulated to represent the
% amplitude/reliability/coherence of the angular data.
%
% Usage: rgbim = showangularim(ang, map);
%        rgbim = showangularim(ang, map, param_name, value, ...);
%
% Arguments:
%            ang - Image of angular data to be displayed.
%            map - Colour map to render the angular data with, ideally a
%                  cyclic colour map. 
%
% Possible param_name - value options 
%
%          'amp' - Amplitude image used to modulate the mapped colours of the
%                  angular data.  If not supplied no modulation of colours is
%                  performed. 
%           'bw' - Flag 0/1 indicating whether the amplitude image is used to
%                  modulate the colour mapped image values towards black, 0
%                  or white, 1.  The default is 0, towards black.
%        'cycle' - The cycle length of the angular data.  Use a value of pi
%                  if the data represents orientations, or 2*pi if the data
%                  represents phase values.  If the input data is in degrees
%                  simply set cycle in degrees and the data will be
%                  rendered appropriately. Default is 2*pi.
%          'fig' - Optional figure number to use. If not specified a new
%                  figure is created. If set to 0 the function runs
%                  'silently' returning rgbim without displaying the image. 
%
% Returns: rgbim - The rendered image.
%
% Parameter name strings can be abbreviated to their first letter except for
% 'amp' which can only be abbreviated to 'am'
%
% For a list of all cyclic colour maps that can be generated by LABMAPLIB use:
% >> labmaplib('cyclic')  
%
% See also: SCALOGRAM, RIDGEORIENT, LABMAPLIB, APPLYCOLOURMAP

% Copyright (c) 2014 Peter Kovesi
% Centre for Exploration Targeting
% The University of Western Australia
% peter.kovesi at uwa edu au
% 
% Permission is hereby granted, free of charge, to any person obtaining a copy
% of this software and associated documentation files (the "Software"), to deal
% in the Software without restriction, subject to the following conditions:
% 
% The above copyright notice and this permission notice shall be included in 
% all copies or substantial portions of the Software.
%
% The Software is provided "as is", without warranty of any kind.

% September 2014
% October   2014 Changed optional argument handling to param_name - value pairs

%function rgbim = showangularim(ang, amp, map, cycle, bw, fig)
function rgbim = showangularim(varargin)
    
    [ang, amp, map, cycle, bw, fig] = parseinputs(varargin{:});
    
    % Apply colour map to angular data.  Some care is needed with this.  Unlike
    % normal 'linear' data one cannot apply shifts and/or rescale values to
    % normalise them.  The raw angular data values have to be respected.
    
    ang = mod(ang, cycle);   % Ensure data values are within range 0 - cycle
    rgbim = applycolourmap(ang, map, [0 cycle]);    
    
    if ~isempty(amp)  % Display image with rgb values modulated by amplitude 
        
        amp = normalise(amp);  % Enforce amplitude  0 - 1
        
        if ~bw  % Modulate rgb values by amplitude fading to black
            for n = 1:3
                rgbim(:,:,n) = rgbim(:,:,n).*amp;
            end
        
        else  % Modulate rgb values by amplitude fading to white
            for n = 1:3
                rgbim(:,:,n) = 1 - (1 - rgbim(:,:,n)).*amp;
            end            
        end
    end
    
    if fig
        show(rgbim,fig)
    end
    
    % If function was not called with any output arguments clear rgbim so that
    % it is not printed on the screen.
    if ~nargout
        clear('rgbim')
    end
    

%-----------------------------------------------------------------------
% Function to parse the input arguments and set defaults

function [ang, amp, map, cycle, bw, fig] = parseinputs(varargin)
    
    p = inputParser;

    numericORlogical = @(x) isnumeric(x) || islogical(x);
    
    % The first arguments are the image of angular data and the colour map.
    addRequired(p, 'ang', @isnumeric); 
    addRequired(p, 'map', @isnumeric);      
    
    % Optional parameter-value pairs and their defaults    
    addParameter(p, 'amp', [], @isnumeric);  
    addParameter(p, 'cycle', 2*pi, @isnumeric);     
    addParameter(p, 'bw', 0, numericORlogical);  
    addParameter(p, 'fig', -1, @isnumeric);  
    
    parse(p, varargin{:});
    
    ang = p.Results.ang;
    map = p.Results.map;    
    amp = p.Results.amp;
    cycle = p.Results.cycle;     
    bw = p.Results.bw;    
    fig = p.Results.fig; 
    if fig < 0,  fig = figure; end
    
    if ~isempty(amp) && ~all(size(amp)==size(ang))
        error('Amplitude data must be same size as angular data');
    end
