function [U,S,V] = lyngby_sop_main(X, R, arg1, arg2, arg3, arg4, ...
    arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, ...
    arg15, arg16)

% lyngby_sop_main      - Strother OPLS
%
%       function [U,S,V] = lyngby_sop_main(X, R,
%           'PropertyName', 'PropertyValue')
%
%       Input:    X   The datamatrix
%                 R   The run structure
%          
%       Property: Paradigm    The paradigm 
%                 Components  { 5 } Number of canonical components 
%                             maintained
%
%       Output:   U   Canonical sequences
%                 S   Canonical values
%                 V   Canonical images
%
%       Orthonormalized partial least square the "Strother way":
%       grouping is based on the intrarun scanindex. This algorithm is
%       based on a singular value decomposition of the inner product
%       between two matrices svd(X'*Y) where Y is constructed as a
%       design matrix with identicator variables based on the intrarun
%       scan index. The lyngby_sdesign function is used to construct Y
%       from R.  
%
%       The optional 'Paradigm' property is only use to get a more
%       prober sign on the canonical vectors. 
%
%       See also LYNGBY, LYNGBY_OPLS, LYNGBY_CVA, LYNGBY_SVD,
%                LYNGBY_SDESIGN, LYNGBY_UI_MAIN, LYNGBY_UI_SOP_INIT. 
%
% $Id: lyngby_sop_main.m,v 1.11 2002/12/17 23:32:00 fnielsen Exp $


    if nargin < 2
      error('Too few input arguments')
    end


    if size(X,1) ~= size(R, 1)
      error(sprintf(['X and R do not have the same length. ',...
	    'X: %dx%d, R: %dx%d'], size(X), size(R)));
    end
    
    % Strother's design matrix
    Y = lyngby_sdesign(R);

    if (size(Y,2) < 2)
      [Runs, ScansPerRun] = lyngby_runinfo(R);
      error(sprintf(['The SOP model will not give any ', ...
	    'meaningfull results if there is only one run.\n', ...
	    'There are %d run with %d scans in.'], Runs, ...
	  ScansPerRun));
    end
    
    % Default parameters
    P = [];
    canValues = 5;
    
    % Parse Properties
    n = 1;
    while n <= nargin-2
      eval(sprintf('arg = lower(arg%d);', n));
      if strcmp(arg, 'paradigm')
	n = n + 1;
	eval(sprintf('arg = arg%d;', n));
	if isreal(arg)
	  if all(size(R) == size(arg))
	    P = arg;
	  else
	    error(sprintf(['The argument to ''Paradigm'' should ' ...
		  'be of the same size as R. Paradigm: %dx%d, ' ...
		  'R: %dx%d'], size(arg), size(R)));
	  end
	else
	  error('The argument with ''Paradigm'' should be a vector.'); 
	end
      elseif strcmp(arg, 'components')
	n = n + 1;
	eval(sprintf('arg = arg%d;', n));
	if isreal(arg)
	  if length(arg) == 1
	    if arg >= 1
	      canValues = arg;
	    else
	      error(['Argument to ''Components'' should ' ...
		    'be a larger than 1']);
	    end
	  else
	    error(['Argument to ''Components'' should ' ...
		  'be a single value']);
	  end
	else
	  error('Argument to ''Components'' should be a value.'); 
	end
      else
	error(sprintf('Invalid property: %s', arg));
      end
      n = n + 1;
    end

    [U,S,V] = lyngby_opls(X,Y, 'Components', canValues);
    
    % Flip the sign of the first canonical sequence and image if we are
    % out of phase with the paradigm
    if ~isempty(P)
      if P'*Y*U(:,1) < 0
	U(:,1) = -U(:,1);
	V(:,1) = -V(:,1);
      end
    end
    





