function [spots] = ppspotreco41(ppcalmat,cent,sp2sp,tilt,scale)
% Function PPSPOTRECO41.M
%
%    [spots] = ppspotreco41(ppcalmat,cent,sp2sp,tilt,scale)
%
%    PPSPOTRECO41 reconstructs the expected hole positions for the Pepperpot
%    emittance scanner.  A 41 x 41 array of holes, each with a horizontal
%    and vertical position, are calculated, based on a calibration matrix
%    PPCALMAT, a central hole position CENT and an image tilt TILT.
%
%    [SPOTS] = PPSPOTRECO41(PPCALMAT) creates a [ 41 x 41 x 3 ] array, SPOTS,
%    that contains the expected location for a grid of spots, based on the
%    position and angle information in the calibration matrix CALMAT:
%    SPOTS(:,:,1) contains the X coordinates, SPOTS(:,:,2) contains the Y
%    coordinates and SPOTS(:,:,3) contains the expected intensities, scaled
%    as a proportion of the expected intensity for the central hole.  Since
%    this intensity information is taken from the calibration matrix,
%    SPOTS(:,:,3) == PPCALMAT(:,:,3).
%
%    [SPOTS] = PPSPOTRECO41(PPCALMAT,CENT) specifies the central position of
%    the central hole in the grid.  CENT must be a [ 2 x 1 ] matrix of the
%    form CENT = [X Y], corresponding to the X and Y pixel locations of the
%    centre of the Pepperpot image: this is usually calculated using
%    PPCALFIND.  If it is not specified, the default value 
%    CENT = [1024 1024] is used.
%
%    [SPOTS] = PPSPOTRECO41(PPCALMAT,CENT,SP2SP) specifies the spot-to-spot
%    spacing of the tungsten mesh, in [number of pixels], also calculated
%    using PPCALFIND.  If it is not specified, the default value SP2SP =
%    50 is used.
%
%    [SPOTS] = PPSPOTRECO41(PPCALMAT,CENT,SP2SP,TILT) specifies the image tilt in
%    radians, also calculated using PPCALFIND.  If it is not specified,
%    the default value TILT = 0 is used ie. no image tilt is assumed.
%
%    [SPOTS] = PPSPOTRECO41(PPCALMAT,CENT,SP2SP,TILT,SCALE) specifies an
%    additional scale factor, SCALE, by which to scale the distances of the
%    spots from the central spot.  This can be used to take out the effect
%    of perspective when looking directly at the phosphor screen, or when 
%    using a non-standard PPCALMAT calibration matrix.
%
%    The input variables are as follows:
%
%    PPCALMAT - the calibration matrix: a [ 41 x 41 x 3 ] matrix of
%    calibration data.  PPCALMAT(:,:,1) contains the distances of the 
%    [ 41 x 41 ] array of holes from the centre hole (ie.
%    PPCALMAT(21,21,1) = 0 ); PPCALMAT(:,:,2) contains the angles of each
%    hole from the positive X-direction (ie. PPCALMAT(21,:,2) ~= 0 ); and
%    PPCALMAT(:,:,3) contains the scaled light intensity of each hole, as a
%    fraction of the light intensity through the central hole (ie.
%    PPCALMAT(21,21,3) = 1 ).
%
%    It should be noted that the distance values ie. PPCALMAT(:,:,1) are
%    scaled by the spot-to-spot spacing AT THE COPPER/PHOSPHOR INTERFACE,
%    which is itself calculated using PPCALFIND from the 9mm-spaced
%    markings on the copper block: this is done within PPSPOTRECO41 by
%    specifying the SP2SP variable.
%
%    PPCALMAT should contain the correctly calibrated distances, based on a
%    tungsten-to-phosphor distance of 10mm.
%
%    CENT - the central point of the grid, CENT = [X Y].  Must be a [ 2 x 1 ]
%    matrix.  Default value is [1024 1024].
%
%    SP2SP - the spot-to-spot spacing, in number of pixels.  The default
%    value is 50.
%
%    TILT - the image tilt in radians.  Default value is 0.
%
%    SCALE - the grid spacing scale factor, by which to scale the distances
%    of the spots from the central spot.  This should only be used for
%    debugging or when another PPCALMAT calibration matrix is used, since
%    PPCALMAT should contain the correctly calibrated distances.
%

    if nargin < 1
        error('Must specify at least 1 input variable: [spots] = ppspotreco(ppcalmat,cent,sp2sp,tilt,scale)') ;
    elseif nargin > 5
        error('Can only specify 5 input variables: [spots] = ppspotreco(ppcalmat,cent,sp2sp,tilt,scale)') ;
    elseif nargout ~= 1
        error('Must specify one output variable: [spots] = ppspotreco(ppcalmat,cent,sp2sp,tilt,scale)') ;
    end

    if nargin < 5
        scale = 1 ;
    end
    if nargin < 4
        tilt = 0 ;
    end
    if nargin < 3
        sp2sp = 50 ;
    end
    if nargin < 2
        cent = [1024 1024] ;
    end

    calsize = size(ppcalmat) ;

    if ( calsize(1) ~= 41 ) | ( calsize(2) ~= 41 ) | ( calsize(3) ~= 3 )
        error('PPCALMAT variable must be a [ 41 x 41 x 3 ] matrix') ;
    elseif ( length(cent) ~= 2 ) | ( sum(cent > 2048) ) | ( sum(cent < 0) )
        error('CENT variable must be a 2x1 matrix with X and Y coordinates between 1 and 2048: CENT = [X Y]') ;
    elseif ( length(tilt) ~= 1 ) | ( tilt > pi ) | ( tilt < -pi )
        error('TILT variable must be a single value angle, in radians, between -pi and pi') ;
    elseif ( scale <= 0 )
        error('SCALE variable must be greater than zero') ;
    end

%    Set up variables

    distmat = ppcalmat(:,:,1).*scale.*sp2sp ;
    angmat = ppcalmat(:,:,2) + tilt ;
    spots  = zeros(calsize) ;
    spots(:,:,3) = ppcalmat(:,:,3) ;

%    Create spot matrix

    for i = 1:calsize(1)
        for j = 1:calsize(2)
            spots(i,j,1) = cent(1) + ( distmat(i,j).*cos(angmat(i,j)) ) ;
            spots(i,j,2) = cent(2) + ( distmat(i,j).*sin(angmat(i,j)) ) ;
        end
    end

    return