function  [data,P] = PLExp2(sbj_number,DB_spec)

%PLEXP2 -- Perceptual Learning Experiment 2 (no feedback)
%
%  [data,P] = PLExp2(sbj_number,[DB_spec])
%
%  SBJ_NUMBER is a number that uniquely identifies the subject.
%  DB_SPEC is either a structure or a string specifying a file name.
%  Both arguments are passed to the function FIND_SBJ_DESCR to
%  determine the subject's group, session, data file name, etc.
%  When not supplied, DB_SPEC defaults to 'PLE2_subjects'.
%
%  P is the 'master parameter structure', cf. PLEXP2_PARAMS.
%  DATA is a matrix with one row per trial and with 21 columns:
%    1. subject number
%    2. subject group
%    3. session (day)
%    4. block
%    5. session trial number
%    ---
%    6. time stamp
%    7. noise orientation (1=negative="Left", 2=positive="Right")
%    8. actual noise orientation (-15 or +15 degrees)
%    9. NCache file number (typically b/n 001:036, 000=newly_generated)
%   10. NCache index (1:300)
%   11. Gabor orientation (1=negative, 2=positive)
%   12. actual Gabor orientation (-10 or +10 degrees)
%   13. difficulty level (max Gabor contrast, 1=0.23,2=0.15,3=0.10,4=demo)
%   14. actual Gabor peak contrast (0.23,0.15,0.10)
%   15. position (1=above fixation, 2=below fixation)
%   16. actual position (in pixels relative to fixation at center screen)
%   17. sanity check -- actual LUT index of STIM(P.Gabor_argmax)
%   ---
%   18. response (1="Left", 2="Right", 0=bad_key)
%   19. correct (1 if response==Gabor_orientation, 0 otherwise)
%   20. response time (in msec from the onset of the stimulus)
%   21. exit code (0='successful trial', 1='bad key', 2='missed frame')
%  The same data are written in a file with name such as 'sbj001.dat'.
%  Note that the date format is different from the one in PLEXP1.
%
%  This file implements the first and longest phase of the experiment.
%  See PLExp2a for phase 2 (test at orthogonal orientations).
%
%  See also IMPORT_PLE2_DATA, DO_PLE2_TRIAL, CACHE_PLE2_BACKGR, PLEXP1.

%  Original coding by Alexander Petrov, UC Irvine.
%  $Revision: 1.0 $  $Date: 2003/08/15 10:30 $

global NOISE_CACHE

%-- Print herald
outs = 1 ;   % output stream = standard output
fprintf(outs,'\nPerceptual learning experiment, ver. 2.\n') ;

%-- Set random generator seed
seed = round(100*sum(clock)) ;    % see RAND's help page
rand('state',seed) ;
fprintf(outs,'\nRandom generator seed set to %d.\n',seed) ;


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%   ALL GLOBAL PARAMETERS ARE IN A SEPARATE FILE   %%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

P = PLExp2_params(1) ;   % <-- Very important file PLEXP2_PARAMS.M


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%      EXPERIMENTAL DESIGN      %%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% Each participant completes 9 days (or 'sessions') of 1200+ trials each.
% Each session consists of 4 blocks of 300+ trials each.
%
% The stimuli are Gabor patches embedded in noise. The noise is filtered
% to have a predominant orientation that can be either positive or 
% negative (see parameter P.noise_orient below). All stimuli within a 
% block have the same noise orientation. Thus there are two kinds of
% blocks: As and Bs.  Block A (or '1') uses P.noise_orient(1) (which
% is negative 15 degrees, see below) while block B (or '2') uses
% P.noise_orient(2) (positive 15 degrees, measured from the vertical).
%
% The experiment has an overall ABAB design, with roughly 2 days in
% each condition. The participants are randomly assigned to two groups.
% The respective schedules are as follows (1 row = 1 session = 4 blocks):

schedule{1} = [1 2 2 2 ; 2 2 2 2 ; 2 1 1 1 ; 1 1 1 1 ;...  %ABBB BBBB...
               1 2 2 2 ; 2 2 2 2 ; 2 1 1 1 ; 1 1 1 1 ; 1 2 2 2] ;
schedule{2} = 3 - schedule{1} ;                  % counterbalance groups

% There are two Gabor orientations (see parameter P.Gabor_orient below).
% The task of the participants is to indicate what Gabor orientation is
% presented on each trial. The main dependent variable is the proportion
% of correct responses. The main independent variable is just time.
% The accuracy (proportion correct) is expected to improve with time
% due to perceptual learning. The purpose of the experiment is to
% determine whether there is any transfer and/or interference across
% blocks with different backgrounds (A vs. B).
%
% The background-noise patches are generated in advance and written on
% a CD-ROM in "caches" of 300. Each cache is in a separate file with
% names such as L01_001.mat, R01_001.mat, L01_002.mat, ... R01_036.mat.
% 
% Once the background orientation is fixed within a block, the stimuli
% vary along the following three dimensions: 
%  - Gabor orientation (with 2 levels, positive and negative)
%  - Gabor peak contrast (with 3 levels, see P.Gabor_Cpeak below)
%  - presentation position on the screen (with 2 levels, see P.position)
% Thus there are 12 different stimuli altogether. Each block contains
% 25 replications of each stimulus, making 300 trials total. The actual
% number of trials may be slightly greater than that because invalid
% trials (e.g. when the subject presses a bad key) are repeated.

levels = {[1 2],...     % indices in P.Gabor_orient, see DO_PLE2_TRIAL
          [1 2 3],...   % indices in P.Gabor_Cpeak , see MAKE_PLE2_STIM
          [1 2]  } ;    % indices in P.position

%-- Session parameters
replications = 25 ;
trials_per_block = 12 * replications ;                 % 2x3x2=12 stimuli


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%   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).

whichScreen = 1 ;         % present stimuli on the auxiliary monitor
viewing_dist = P.viewing_dist ;   % 720 milimeters, +/-10%
mm_pix = P.mm_pix ;       % 0.5655 miliimeters/pixel
deg_pix = mm_pix/viewing_dist * 180/pi ;   % 0.045 degree/pixel, +/-10%

%GAMMA = P.LUT_params.gamma ;      % 1.5,  07-30-03
%BRstep = P.LUT_params.BRstep ;    %  24, hardwired

msec_frame = P.msec_frame ;        % 8.3 = 1000/120 ; (120 Hz)
pixel_depth = 32 ;      % must be 32 bits
if (~ismember(pixel_depth,SCREEN(whichScreen,'PixelSizes')))
   error('Sorry, I need a screen that supports 32-bit pixel depth.') ;
end
if (SCREEN('Preference','Backgrounding'))
   warning('I turn Backgrounding off because it confuses CharAvail.');
   SCREEN('Preference','Backgrounding',0) ;  % see CharAvail's help page
end


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

%- Main parameters are the same as in PLExp1.  See PLEXP1_PARAMS.M
%- Gabor parameters. See PLEXP2_PARAMS and GABOR.M
%- Filtered noise parameters. See MAKE_PLE2_BACKGR, CACHE_PLE2_BACKGR.
%- Lookup table parameters. See IMAGE/MAKE_LINEAR_LUT.M
gray = P.colors.gray ;
%- Trial parameters


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

%- P.mask_idx  -- See PLEXP2_PARAMS.M
%- P.Gabor -- See PLEX2_PARAMS, MAKE_PLE2_STIM, GABOR.M
%- P.Filter is not really necessary because of NOISE_CACHE global var
%- P.LUT -- lookup table, installed later.
%- P.sounds, P.fixation, and P.blank -- See PLEXP2_PARAMS.M


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%   ACQUAINT WITH PARTICIPANT   %%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

if (nargin < 2)  DB_spec = 'PLE2_subjects' ; end    % default

%-- Open the subject database
if (ischar(DB_spec))
   fprintf(outs,'Consulting the participant data base %s.mat...\n',...
           DB_spec) ;
   DB = open_sbj_database(DB_spec) ;
elseif (isstruct(DB_spec))
   DB = DB_spec ;
else
   error('DB_SPEC must be either a file name or a structure array.') ;
end

%-- Look for entries with this particular subject number
sbj_descr = find_sbj_descr(sbj_number,DB) ;
if (isempty(sbj_descr))
   fprintf(outs,'It appears that we have a new participant.\n') ;
   %- Let's see how many subjects in each group we have so far
   group = [DB(:).group]' ;
   if (sum(group==1) < sum(group==2))
      group = 1 ;
   elseif (sum(group==1) > sum(group==2))
      group = 2 ;
   else   % equal number of Ss in each group so far
      group = floor(2*rand) + 1 ;      % break ties randomly
   end
   %- Make a new 'subject descriptor'
   sbj_descr = new_sbj_descr(sbj_number,group) ;  % ask for name, etc.
   %- Generate a sequence of 'NCache file numbers'
   sched_length = length(schedule{group}(:)) ;    % should be 36
   fprintf(outs,'NCache file sequence generated (L=%d).\n',sched_length);
   sbj_descr.NCache_sequence = randperm(sched_length) ;
%else information about this subject successfully retrieved from DB
end

%-- Make sure all fields of SBJ_DESCR are correct
sbj_descr    % print on console as a structure
k = input('Is this information correct? (y) ','s') ;
if (isempty(k))  k = 'y' ;  end   % default
if (~ismember(k,'yY'))
   fprintf(outs,'\n\nYou may edit the SBJ_DESCR variable.\n') ;
   fprintf(outs,'Type ''return'' to continue.\n\n') ;
   keyboard ;
end

%-- Save the (edited?) subject descriptor in the database
DB = update_sbj_database(sbj_descr,DB_spec) ;  % write file as side eff

%-- Individualized session parameters
sbj_number = sbj_descr.sbj_number ;
group = sbj_descr.group ;
session = sbj_descr.session ;
data_filename = sbj_descr.filename ;
NCache_sequence = sbj_descr.NCache_sequence ;

curr_schedule = schedule{group}(session,:) ;
blocks_per_session = length(curr_schedule) ;          % 4
N_trials = trials_per_block * blocks_per_session ;    % 1200=300x4
if (session==1)
   N_demo_trials = 10 ;     % as in PLExp1, with feedback
else
   N_demo_trials = 2 ;      % as in PLExp1, with feedback
end


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%    SCREENS AND MOVIES     %%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

%-- Open a SCREEN window and set the lookup table
fprintf(outs,'\nOpening screen %d...',whichScreen) ;
[winPtr,winRect] = SCREEN(whichScreen,'OpenWindow',gray,[],pixel_depth) ;
fprintf(outs,'   Done.\nSetting the lookup table...') ;
SCREEN(winPtr,'SetClut',P.LUT) ;
SCREEN(winPtr,'FillRect',gray) ;    % clear the screen
fprintf(outs,'   Done.\n') ;

%-- Convert stimulus duration from milliseconds to video frames
N_frames = round(P.duration / msec_frame) ;
if (abs(N_frames - (P.duration/msec_frame)) > 0.01)
   warning('Stimulus duration is not an integer number of frames.') ;
end
P.times.target_play = (N_frames+1) * msec_frame/1000 ;  % one blank frame

%-- Create one movieStruct for each stimulus position
fprintf(outs,'Creating offscreen buffers...') ;
P.movieStruct(1) = MakeMovieStruct(winPtr,repmat(P.size,2,1),...
                                   P.position{1},[1 2],[N_frames 1]) ;
for k = 2:length(P.position)
   P.movieStruct(k) = CloneMovieStruct(P.movieStruct(1),P.position{k}) ;
end
fprintf(outs,'   Done.\n') ;

%%%%%%  At this point, P is ready to be passed to DO_PLE2_TRIAL.  %%%%%%


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%    LOAD THE FIRST NOISE CACHE     %%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

NCache_path = P.NCache_params.path ;           % 'PLE2_CACHE01'
NCache_template = P.NCache_params.fname ;      % 'L01_%03d.mat'

bl = 1 ;    % first N.C. in the sequence used in both demo and block 1
total_bl = blocks_per_session*(session-1) + bl ;   % since day 1
backgr_orient = curr_schedule(bl) ;
NCache_fnumber = NCache_sequence(total_bl) ;
NCache_fname = fullfile(NCache_path, ...
   sprintf(NCache_template{backgr_orient},NCache_fnumber)) ;

fprintf(outs,'Loading stimuli from %s. Please wait ...',NCache_fname) ;
SCREEN(winPtr,'WindowToFront') ;
SCREEN(winPtr,'DrawText','Loading stimuli, please wait...',...
       200,240,P.colors.black) ;
NC_pages = load_NOISE_CACHE(NCache_fname,P.size) ;   % local fun, glob var
fprintf(outs,'   Done.\n') ;
SCREEN(winPtr,'FillRect',gray) ;


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%    PREPARATION    %%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

%-- Open the data file
fprintf(outs,'Opening data file %s...',data_filename) ;
[data_fid,errmsg] = fopen(data_filename,'at') ;   % mode = append text
if (data_fid == -1)
   warning(errmsg) ;
   fprintf(outs,'Fix the problem and type ''return'' to continue.\n\n') ;
   keyboard ;
else
   fprintf(outs,'   Done.\n') ;
end

%-- Open the sound channel
fprintf(outs,'Opening the sound channel...') ;
SND('Open') ;
fprintf(outs,'   Done.\n') ;

%-- Start various counters
data = zeros(N_trials+N_demo_trials+200,21) ;   % 200 reserve rows
d = zeros(1,21) ;

time_zero = GetSecs ;
exp_tr = 1 ;           % global trial number

%-- Wait for confirmation before presenting the demo
FlushEvents('keyDown') ;
SCREEN(winPtr,'WindowToFront') ;
ask(winPtr,'Please press Enter to proceed to a short demo... ',...
           P.colors.black,gray,'GetString') ;
SCREEN(winPtr,'FillRect',gray) ;
WaitSecs(1.000) ;


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%    DEMO TRIALS WITH FEEDBACK   %%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

block = factor_design([2 2],ceil(N_demo_trials/4),1) ;
demo_diff = length(P.Gabor_Cpeak) ;     % demo contrast level
backgr_orient = curr_schedule(1) ;      % as in block 1
bl = 0 ;        % demo block has block_number=0

NC_idx = randomize_NC_idx(N_demo_trials,NC_pages) ;
for tr = 1:N_demo_trials
   % Present a stimulus and get a response from the subject
   spec = [block(tr,1),demo_diff,block(tr,2)] ;   % [orient,diff,pos]
   record = do_PLE2_trial(P,spec(1),spec(2),NC_idx(tr),spec(3)) ;
   % Give auditory feedback -- during the demo only
   if (record(8)~=1)           % if incorrect response or bad key
      SND('Play',P.sounds.wrong) ;
   end
   % Always beep them on bad keys
   if (record(10)~=0)
	  SND('Play',P.sounds.badkey) ;
   end
   % Record data: 1=sbj, 2=group, 3=session, 4=block, 5=trial, ...
   d([1 2 3 4 5]) = [sbj_number group session bl exp_tr] ;
   d(6) = record(1) - time_zero ;    % 6=time stamp
   % 7=noise_orient, 8=noise_degr, 9=NC_file, 10=NC_idx
   d([7 8]) = [backgr_orient,P.noise_orient(backgr_orient)*180/pi] ;
   d([9 10]) = [NCache_fnumber,record(4)] ;
   % 11=Gabor_orient, 12=Gabor_degr, 13=diff, 14=Cpeak
   d([11 12]) = [record(2),P.Gabor_orient(record(2))*180/pi] ;
   d([13 14]) = [record(3),P.Gabor_Cpeak(record(3))] ;
   % 15=position, 16=dy, 17=sanity_check
   d([15 16]) = [record(5),P.position{record(5)}(2)] ;
   d(17) = record(6) ;     % actual luminance of a particular pixel
   % 18=response, 19=correct, 20=RT, 21=exit_code
   d(18) = record(7) ;     % response key: 1="Left",2="Right"
   d(19) = record(8) ;     % correct = (resp==Gabor_orient)
   d(20) = record(9) ;     % response time, msec
   d(21) = record(10) ;    % exitcode: 0=OK,1=badKey,2=missFr
   % Write data file. See IMPORT2_PLE_DATA and the subfunction below.
   data(exp_tr,:) = d ;
   record_data_file(data_fid,d) ;
   % Move on to the next trial
   exp_tr = exp_tr+1 ;
   WaitSecs(P.times.ITI) ;
end  % of demo


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%        MAIN   LOOP        %%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

for bl = 1:blocks_per_session   % for each block in the current session
   %- Keeping BACKGR_ORIENT fixed, counterbalance the other IVs
   backgr_orient = curr_schedule(bl) ;
   block = factor_design(levels,replications ,1) ;   % randomized
   %- Load the appropriate NOISE_CACHE from the CD-ROM
   if (bl > 1)   % the first block is already loaded for the demo
     total_bl = blocks_per_session*(session-1) + bl ;   % since day 1
     NCache_fnumber = NCache_sequence(total_bl) ;
     NCache_fname = fullfile(NCache_path, ...
                  sprintf(NCache_template{backgr_orient},NCache_fnumber)) ;
     fprintf(outs,'Loading stimuli from %s. Please wait ...',NCache_fname);
     SCREEN(winPtr,'WindowToFront') ;
	 SCREEN(winPtr,'DrawText',['Loading stimuli, please wait...   ',...
               '(Take a break if you wish.)'],150,240,P.colors.black) ;
     NC_pages = load_NOISE_CACHE(NCache_fname,P.size) ;     % <-- sic!
     fprintf(outs,'   Done.\n') ;
	 SCREEN(winPtr,'FillRect',gray) ;
   end
   %- Generate randomized Noise Cache indices
   NC_idx = randomize_NC_idx(trials_per_block,NC_pages) ;
   %- Proceed when the participant is ready
   FlushEvents('keyDown') ;
   SCREEN(winPtr,'WindowToFront') ;
   ask(winPtr,'Please press Enter to proceed to the next trial... ',...
              P.colors.black,gray,'GetString') ;
   SCREEN(winPtr,'FillRect',gray) ;
   WaitSecs(0.800) ;
   %- Main trial loop
   tr = 1 ;      % block trial number, don't confuse with exp_tr
   while (tr <= size(block,1))
      % Present a stimulus and get a response from the subject
      spec = block(tr,:) ;    % [Gabor_orient,difficulty,position]
      record = do_PLE2_trial(P,spec(1),spec(2),NC_idx(tr),spec(3)) ;
      % Did everything go OK?
      exitcode = record(10) ;     % see DO_PLE2_TRIAL
      if (exitcode ~= 0)          % something went wrong
         block = [block;spec] ;   % repeat same trial at end of block
		 NC_idx = [NC_idx,NC_idx(tr)] ;
      end
      % Record data: 1=sbj, 2=group, 3=session, 4=block, 5=trial, ...
      d([1 2 3 4 5]) = [sbj_number group session bl exp_tr] ;
      d(6) = record(1) - time_zero ;    % 6=time stamp
      % 7=noise_orient, 8=noise_degr, 9=NC_file, 10=NC_idx
      d([7 8]) = [backgr_orient,P.noise_orient(backgr_orient)*180/pi] ;
      d([9 10]) = [NCache_fnumber,record(4)] ;
      % 11=Gabor_orient, 12=Gabor_degr, 13=diff, 14=Cpeak
      d([11 12]) = [record(2),P.Gabor_orient(record(2))*180/pi] ;
      d([13 14]) = [record(3),P.Gabor_Cpeak(record(3))] ;
      % 15=position, 16=dy, 17=sanity_check
      d([15 16]) = [record(5),P.position{record(5)}(2)] ;
      d(17) = record(6) ;     % actual luminance of a particular pixel
      % 18=response, 19=correct, 20=RT, 21=exit_code
      d(18) = record(7) ;     % response key: 1="Left",2="Right"
      d(19) = record(8) ;     % correct = (resp==Gabor_orient)
      d(20) = record(9) ;     % response time, msec
      d(21) = record(10) ;    % exitcode: 0=OK,1=badKey,2=missFr
      % Write data file. See IMPORT2_PLE_DATA and the subfunction below.
      data(exp_tr,:) = d ;
      record_data_file(data_fid,d) ;
      % Move on to the next trial
      tr = tr+1 ;
      exp_tr = exp_tr+1 ;
      WaitSecs(P.times.ITI) ;
   end  % of the main trial loop
end  % of the block loop

data(exp_tr:end,:) = [] ;    % cut out unused reserve DATA rows


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%      SHOW DIAGNOSTIC RESULTS       %%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

ok = find((data(:,21)==0) & (data(:,4)>0)) ;    % valid non-demo trials
correct = data(ok,19) ;
RT = data(ok,20) ;
fprintf(outs,['\n%d trials completed. %4.1f percent correct. ',...
             'Median RT=%d msec.\n'],exp_tr-1,...
			 mean(correct)*100,round(median(RT)) ) ;
if (length(ok)==N_trials)                            % if all went well
	sz = [trials_per_block,blocks_per_session] ;     % [300x4]
	mnP = mean(reshape(correct,sz)) * 100 ;
	medRT = round(median(reshape(RT,sz))) ;
	fprintf(outs,'   P = [ ') ; fprintf(outs,'%4.1f ',mnP) ;
	fprintf(outs,']  ;  RT = [ '); fprintf(outs,'%d ',medRT) ;
	fprintf(outs,']\n\n') ;
end


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%         CLEAN  UP         %%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

fprintf(outs,'Closing data file %s...',data_filename) ;
fclose(data_fid) ;
fprintf(outs,'   Done.\nClosing all screens and screen buffers...') ;
SCREEN('CloseAll') ;
fprintf(outs,'   Done.\nClosing the sound channel...') ;
SND('Close') ;
fprintf(outs,'   Done.\n') ;

%-- Update the subject database, if the name of the file is known
if (ischar(DB_spec))
   fprintf(outs,'Updating the participant data base %s...',DB_spec) ;
   session_log.session = session ;
   session_log.date = date ;            % e.g. '18-Aug-2003'
   session_log.trials = exp_tr-1 ;
   sbj_descr.session_log(end+1) = session_log ;
   sbj_descr.session = session + 1 ;    % prepare for next session
   DB = update_sbj_database(sbj_descr,DB_spec) ;  % write to file
   fprintf(outs,'   Done.\n') ;
end

fprintf(outs,'\nThank you for your participation. Have a nice day!\n\n') ;

%--- Return DATA and P
%%%  End of the main function


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%% SUBFUNCTIONS

function  NC_pages = load_NOISE_CACHE(NCache_fname,sz)      %%%%%%%%%%%%%
% Update global variable NOISE_CACHE using the specified CD-ROM file.

global NOISE_CACHE

NOISE_CACHE = [] ;             % clear the old one
load(NCache_fname) ;           % <-- Sic!  Error-cheking below

[NC_rows,NC_cols,NC_pages] = size(NOISE_CACHE) ;
if (NC_rows~=sz(1) | NC_cols~=sz(2))
   NC_pages = 0 ;
   warning(sprintf('Failed to load NOISE_CACHE from %s.',NCache_fname)) ;
   fprintf(outs,'Fix the problem and type ''return'' to continue.\n\n') ;
   keyboard ;
%else  NC_pages correctly set
end

%-- Return NC_PAGES
%%% End of subfunction LOAD_NOISE_CACHE


function  NC_idx = randomize_NC_idx(N_trials,NC_pages)
% Make sure that there is a valid Noise Cache index for each trial

if (NC_pages==N_trials)     % the typical case
   NC_idx = randperm(NC_pages) ;        % use each exactly once
else         % in case I generate larger/smaller caches later
   NC_pool = repmat(randperm(NC_pages),1,ceil(N_trials/NC_pages)) ;
   NC_idx = NC_pool(1:N_trials) ;
end

%-- Return NC_IDX
%%% End of subfunction RANDOMIZE_NC_IDX


function  record_data_file(dfid,d)      %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Write data file, see IMPORT_PLE2_DATA

% 1=sbj, 2=group, 3=session, 4=block, 5=trial
fprintf(dfid,'%02d %2d %2d %2d %4d',d(1:5)) ;
fprintf(dfid,'%10.3f  ',d(6)) ;            % 6=time stamp
% 7=noise_orient, 8=noise_degr, 9=NC_file, 10=NC_idx
fprintf(dfid,'%2d%+6.1f %03d %03d ',d(7:10)) ;
% 11=Gabor_orient, 12=Gabor_degr, 13=diff, 14=Cpeak
fprintf(dfid,'%2d%+6.1f %3d %4.2f  ',d(11:14)) ;
% 15=position, 16=dy, 17=sanity_check
fprintf(dfid,'%2d %+5d  %3d   ',d(15:17)) ;
% 18=response, 19=correct, 20=RT, 21=exit_code
fprintf(dfid,'%2d %2d %6d %2d\n',d(18),d(19),round(d(20)),d(21)) ;

%-- Return no value
%%% End of subfunction RECORD_DATA_FILE


%%%%% End of file PLEXP2.M
