function  P = PLExp1_params(level)

%PLEXP1_PARAMS -- Parameters for the Perceptual Learning Experiment 1
%
%  P = PLExp1_params()
%  P = PLExp1_params(level)
%
%  An excerpt from the main program PLEXP1 -- only the stimulus parameters
%  are retained and returned as a 'master parameter structure' P suitable
%  for passing to MAKE_PLE_STIM.
%  Note that PLEXP1 does not call PLEXP1_PARAMS; it calculates everything
%  from scratch on its own and it is the version that drives the actual
%  experimental presentations. The excerpt in this file reflects the
%  parameter settings used for the 13 subjects in Perceptual Learning
%  Experiment 1 between January and February 2002.
%
%  LEVEL 0: as if produced by the main program PLEXP1, except 'movieStruct'
%  LEVEL 1: omit fields 'sounds', 'LUT', 'fixation', and 'keys'
%  LEVEL 2 (default): omit level 1 fields and add some extras such
%    as 'deg_pix', 'viewing_dist', 'msec_frame', and 'N_frames'.
%
%  See also PLEXP1, MAKE_PLE_STIM.

%  Original coding by Alexander Petrov, UC Irvine.
%  $Revision: 1.0 $  $Date: 2002/03/12 17:00 $

if (nargin < 1)  level = 2 ;   end   % default


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%   EQUIPMENT CHARACTERISTICS   %%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% NANAO Technology FlexScan 6600 paperwhite monitor with a P4 phosphor.
% Driven by the internal videocard of a Power Macintosh 7300/200.
% A special circuit combines two 8-bit output channels of the video-
% card to produce 24*256=6144 distinct gray levels (see MAKE_LINEAR_LUT).

viewing_dist = 720 ;  % milimeters, +/-10%
mm_pix = 0.5655 ;     % miliimeters/pixel [resol. 640x480, 19" monitor]
deg_pix = mm_pix/viewing_dist * 180/pi ;   % 0.045 degree/pixel, +/-10%

GAMMA = 1.95 ;        % =mean([1.91 1.99])  % on 10-30 and 12-12-0
BRstep = 24 ;         % hardwired in the special circuit

msec_frame = 1000/120 ; % must be 8.3 msec/frame (120 Hz)


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%   PARAMETER DEFINITIONS   %%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

%-- Main parameters. Determined via pilot studies (see PILOT2.M).
% 64 pixels = 2.88 degrees of visual angle viewed from approx 720 mm.
P.size = [64 64] ;       % pixels, this scales everything else
P.duration = 75 ;        % msec, must be a multiple of MSEC_FRAME
P.Gabor_orient = [-10 +10] .* pi/180 ;
P.noise_orient = [-15 +15] .* pi/180 ;   % max power around +/-15 deg
P.noise_Cpeak = 0.66667 ;                % peak contrast of the noise
P.Gabor_Cpeak = [0.23 0.15 0.10 0.50] ;  % 3 difficulty levels + 1 demo
  % The peak contrasts 0.23, 0.15, and 0.10 were shown to yield approx.
  % 80%, 70%, and 60% correct for novice observers (see PILOT2.M).
  % The last value in the list is for demo trials only.

%-- Gabor parameters. See functions GABOR and GABOR_PARAMS for details
P.Gabor_params.phase = pi/2 ;
P.Gabor_params.freq = 2*deg_pix ;    % 2 cycles/deg --> 1/11.1 cycles/pix
P.Gabor_params.sigma = 0.4/deg_pix ; % 0.4 degrees --> 8.89 pixels

%-- Filtered noise parameters. See functions BUTTERWORTH2 and FILTNOISE.
P.noise_params.sigma = 0.15 ;   % Gaussian with mean 0 and std.dev. SIGMA
P.noise_params.cutoff = 0.20 ;  % see BUTTERWORTH2 for details
P.noise_params.outcut = 4.0 ;   % FILTNOISE outlier cutoff

%-- Lookup table parameters. See IMAGE/LUT_PARAMS and IMAGE/MAKE_SPLIT_LUT.
P.LUT_params.gamma = GAMMA ;
P.LUT_params.BRstep = BRstep ;
P.LUT_params.contrast = 1.0 ;   % use the full dynamic range of the monitor
P.LUT_params.domain = [0 255] ;

%-- Trial parameters
dy = round(5.0/deg_pix) ;         % 5.0 degrees --> 111 pixels
P.position = {[0 -dy],[0 +dy]} ;  % dx=0, dy=+/-111 pixels off fixation
P.times.fix_onset = 0.500 ;     % fixation appears approx 500 msec before
P.times.alert_onset = 0.250 ;   % sound alert approx 250 msec before stim
P.times.fix2alert = P.times.fix_onset - P.times.alert_onset ;
P.times.wrong_delay = 0.100 ;   % during auditory feedback
P.times.ITI = 0.750 ;           % inter-trial interval, seconds
if (level==0)
  P.keys = {'sdfecSDFEC','jklimJKLIM'} ;    % {negKeys,posKeys}
end

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%   REUSABLE DATA STRUCTS   %%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

%-- Everything happens in the following oval window
Xmin = -floor(P.size(1)/2) ; Ymin = -floor(P.size(2)/2) ;
[X,Y] = meshgrid([1:P.size(1)]+Xmin,[1:P.size(2)]+Ymin) ;
oval = (X.^2)./(Xmin.^2) + (Y.^2)./(Ymin.^2) ;
P.mask_idx = find(oval > 1) ;

%-- Calibrate GABOR_PARAMS so that the peak amplitude is 1.0
params = P.Gabor_params ;
params.amplit = 1.0 ;
params.orient = P.Gabor_orient(1) ;  % just for calibration
A = gabor(X,Y,params) ;
Cpeak = max(abs(A(:))) ;             % Cpeak < 1.0  because PHASE=pi/2
P.Gabor_params.amplit = params.amplit / Cpeak ;   % augment P
params.amplit = P.Gabor_params.amplit ;           % 1.0639

%-- Now make one Gabor patch for each orientation and difficulty level
P.Gabor = zeros([P.size length(P.Gabor_orient) length(P.Gabor_Cpeak)]) ;
for k = 1:length(P.Gabor_orient)
   params.orient = P.Gabor_orient(k) ;
   A = gabor(X,Y,params) ;
   for l = 1:length(P.Gabor_Cpeak)
      P.Gabor(:,:,k,l) = A .* P.Gabor_Cpeak(l) ;
   end
end

%-- Prepare filters for later calls to FILTNOISE
[Fx,Fy] = fftmesh(P.size) ;   % filter the noise patch
P.Filter = zeros([P.size length(P.noise_orient)]) ;
for k = 1:length(P.noise_orient)
   theta = P.noise_orient(k) + pi/2 ;     % orientation in Fourier space
   P.Filter(:,:,k) = butterworth2(Fx,Fy,theta,P.noise_params.cutoff) ;
end

%-- Lookup table (constructed here, installed later)
[LUT,gray] = make_linear_LUT(LUT_params) ;
if (level==0)  P.LUT = LUT ; end
P.colors.black = P.LUT_params.domain(1) ;
P.colors.gray = gray ;
P.colors.white = P.LUT_params.domain(2) ;
P.LUT_params.span = min(gray-P.colors.black,P.colors.white-gray) ;

%-- Sounds
if (level==0)
  P.sounds.alert = MakeBeep(500,0.100) ;  % 500 Hz, 100 msec
  P.sounds.wrong = MakeBeep(300,0.150) ;  % 300 Hz, 150 msec
end

%-- Fixation crosshair
if (level==0)
  P.fixation = repmat(gray,9,9) ;
  P.fixation(:,[4:6]) = P.colors.black ;
  P.fixation([4:6],:) = P.colors.black ;
  P.blank = repmat(gray,P.size) ;         % used to clear screen
end

%-- Convert stimulus duration from milliseconds to video frames
N_frames = round(P.duration / msec_frame) ;
P.times.target_play = (N_frames+1) * msec_frame/1000 ;  % one blank frame

%%%%%%  LEVEL 2  %%%%%%
if (level==2)
   P.viewing_dist = viewing_dist ;
   P.mm_pix = mm_pix ;
   P.deg_pix = deg_pix ;
   P.msec_frame = msec_frame ;
   P.N_frames = N_frames ;
   P.x = X(1,:) ;
end

%--- Return P
%%%%% End of file PLEXP1_PARAMS.M