function  [rep,N] = PLFrontend(stim,Idef)

%PLFRONTEND -- Input transformation of the Perceptual Learning Model
%
%  rep = PLFrontend(stim,Idef)
%
%  STIM is a grayscale image (see MAKE_PLE_STIM).
%  IDEF is a "front-end definition structure" produced by MAKE_PLFRONTEND.
%   [MAKE_PLFRONTEND stores a number of reusable data structures (such as]
%   [filter FFTs) in the global variable FRONTEND_MEMOIZATION. It *MUST* ]
%   [be updated whenever IDEF is changed by calling MAKE_PLFRONTEND again]
%  The result REP is a row vector representing the stimulus image STIM.
%
%  The stimulus is converted into a bank of local energy maps at various
%  orientations and frequencies (see PLM_STIM_ENERGY).
%  A normalization term is computed according to the following algorithm:
%   1. square the local energy (thus going to 4th power of image contrast)
%   2. for each spatial frequency, average across all orientations and
%      spatial locations
%   3. pool across spatial frequency bands according to CGC_FPOOL matrix
%   4. take square root to reverse the squaring in step 1.
%  The normalization vector N has one element per spatial frequency.
%  All local eneries are divided by the corresponding normalization term
%  to produce "normalized energy maps":  nE(x,y,o,f)=E(x,y,o,f)/(N(f)+C).
%  The additive constant in the denominator is CGC_CONST, usually 0.
%  Finally, the normalized energy maps are pooled across space weighted
%  by a radial Gaussian kernel with full width at half height FW_INTEGR.
%
%  After all said and done, the function returns REP -- the internal
%  representation of the image STIM in the PLM model. It is a row
%  vector with  N_rep=N_orient*N_spfreq  elements. The function
%  CACHE_INPUTS calls PLFrontend repeatedly to generate a "cache"
%  that is then used by the learning model (see PLMODEL1, etc.).
%
%  Example:
%    Idef=make_PLFrontend(PLM_input_params);o=Idef.D_orient;No=length(o);
%    P=PLExp1_params; stim=make_PLE_stim(P,1,1,2); Nf=Idef.N_spfreq;
%    rep=PLFrontend(stim,Idef); plot(o,reshape(rep,No,Nf),'.-');
%    for f=1:Nf l{f}=sprintf('%.1f c/d',Idef.D_spfreq(f));end;legend(l(:));
%
%  See also MAKE_PLFRONTEND, PLMODEL, CACHE_INPUTS, PLM_STIM_ENERGY.

%  Original coding by Alexander Petrov, UC Irvine.
%  $Revision: 2.2 $  $Date: 2002/08/08 16:00 $

global FRONTEND_MEMOIZATION

%-- Decipher IDEF
% Cache integrity will be checked (sort of) by PLM_STIM_ENERGY
N_orient = Idef.N_orient ;               % default 7
N_spfreq = Idef.N_spfreq ;               % default 5
N_centers = size(Idef.centers,1) ;       % default 2
N_pixels = prod(Idef.img_size) ;         % 4096 = 64*64

%-- Local energy map
E = reshape(PLM_stim_energy(stim,Idef),[N_pixels,N_orient,N_spfreq]) ;

%-- Normalization term
% References: Heeger, D.J. (1992). Normalization of cell responses in
%   cat striate cortex, Visual Neuroscience, 9, 181-197. [Equation 4]
% Cannon, M.W. & Fullenkamp, S.C. (1991). Spatial interactions in
%   apparent contrast: Inhibitory effects among grating patterns of
%   different spatial frequencies, spatial positions, and orientations.
%   Vision Research, 31 (11), 1985-1998.
% Squared energy --> fourth power of raw contrast
N2 = squeeze(mean(E.^2,2)) ;   % pool across all orientations, [4096x5]
N2 = mean(N2)' ;               % pool across all pixels, [5x1]
% Pool across spatial frequency bands according to CGC_FPOOL matrix
N2 = Idef.CGC_Fpool*N2 + Idef.CGC_const ;    % [5x1] = [5x5]*[5x1] + C
% Final normalization term -- one value per spatial frequency
N = sqrt(N2) ;                 % [5x1], 2nd power of raw contrast
N = repmat(N',N_orient,1);     % [7x5]
N = repmat(N(:),N_centers,1)' ;  % [1x70] {111222...555 111222...555}

%-- Pool across space in different "basins" and apply the normalization
W = FRONTEND_MEMOIZATION.Gausswgt ;       % [2x4096], where 2=N_centers
pooled_E = W * reshape(E,N_pixels,N_orient*N_spfreq) ;        % [2x35]
pooled_E = reshape(pooled_E',1,N_orient*N_spfreq*N_centers) ; % [1x70]

rep = pooled_E ./ N ;     % [1x70]

%--- Return REP
%%%%% End of file PLFRONTEND.M
