Code and Output

Code 12.3.1:

% Construct a File1.txt to use for the example
fileout1 = fopen('File1.txt','wt');
fprintf(fileout1,'THIS IS THE CONTENTS OF THE FIRST FILE\n');
fclose(fileout1);

% Now test for the existence of File1.txt
if exist('File1.txt','file') == 2
    mybutton = questdlg('Delete old File1.txt? ','File1','Yes');
    switch mybutton
        case 'Yes'
            delete('File1.txt');
            msgbox('File1.txt deleted!')
        case {'No' 'Cancel'}
            msgbox('File1.txt unchanged...Exiting','','warn')
            return
    end
end

Code 12.3.2:

% Make sure File1.txt exists for the example
fileout1 = fopen('File1.txt','wt');
fprintf(fileout1,'THIS IS THE CONTENTS OF THE FIRST FILE\n');
fclose(fileout1);

% Read in a file, change it, and write out the modified file.
infilename = uigetfile('*.txt')
theText = fileread(infilename);
theText = strrep(theText,'FIRST','SECOND');
fileout2 = fopen('File2.txt','wt');
fprintf(fileout2,theText);
fclose(fileout2);

% Verify that the updated text is now in File2.txt
msgbox('File2.txt successfully created,','All done!','Help')
fprintf('\nContents of File2.txt:')
type File2.txt

Output 12.3.2:

infilename =
File1.txt

Contents of File2.txt:
THIS IS THE CONTENTS OF THE SECOND FILE

Code 12.4.1:

h = figure;
set(h,'position',[   427  306   512   100])
hpb = uicontrol('Style', 'pushbutton',...
    'String', 'Make a sound!',...
    'Position', [20 20 150 20],...
    'Callback', 'beep');
pause(10)
close(h);

Output 12.4.1:

Output 12.4.1

Code 12.4.2:

function main
beepcount = 0;
h = figure;
hpb = uicontrol('Style', 'pushbutton',...
    'String', 'Click to Beep!',...
    'Position', [150 100 200 200],...
    'Callback', @beepcallback);
pause(10)
close(h);
msgbox(sprintf('Counted %d beeps!',beepcount));
return

    function beepcallback(source,eventdata)
        beep
        beepcount = beepcount + 1;
        return
    end

end

Output 12.4.2:

Output 12.4.2

Code 12.4.3:

function main;
% Initialize variables common to main and nested subfunctions
month = 'January';
year = 2001;
% Open the figure for the interface
handletothefigure = figure;

% Install a popup menu for the months
monthstrings = {
    'Month'
    'January'
    'February'
    'March'
    'April'
    'May'
    'June'
    'July'
    'August'
    'September'
    'October'
    'November'
    'December'};
hmonth = uicontrol('Style', 'popupmenu',...
    'String',monthstrings,...
    'Position', [120 320 100 20],...
    'Callback', @monthcallback);

% Install a popup menu for the years
hyear = uicontrol('Style', 'popupmenu',...
   'String',...
   'Year|2008|2009|2010|2011|2012|2013|2014|2015|2016|2017|2018',...
   'Position', [220 320 100 20],...
   'Callback', @yearcallback);

% Install an informative text field for the popup controls
uicontrol('Style','text','String','Pick a month and a year: ',...
     'Position', [120,360,200,15]);

% Install a GO button
hgobutton = uicontrol('Style','pushbutton',...
    'String','Look up days in the month',...
    'Position', [120 120 200 40],...
    'Callback', @gobuttoncallback);

% Now just wait for the user to finish (when the window closes);
uiwait(handletothefigure)
return % from main

% Callback routines in nested functions:
    function monthcallback(source,eventdata)
        mylist = (get(source,'String'));
        myitem = (get(source,'Value'));
        month = char(mylist(myitem));
    end

    function yearcallback(source,eventdata)
        mylist = (get(source,'String'));
        myitem = (get(source,'Value'));
        year = str2num(mylist(myitem,:))
    end

    function gobuttoncallback(source,eventdata)
        hmsg = msgbox(sprintf(...
          'Will compute days for %s, %d\n\n',month, year));
        uiwait(hmsg)
% When user presses the "go" button, the computation from
% Code 7.3.6 would be executed here, to return the results
% (code to be inserted).
        close(handletothefigure)
    end

end %function main

Output 12.4.3:

Output 12.4.3

Output 12.5.1:

Output 12.5.1

Code 12.6.1:

commandwindow
tic
response = input('What is five plus the square root of 64? ')
Reaction_Time = toc

Output 12.6.1:

response =
13
Reaction_Time =
2.2859

Code 12.6.2:

function RunaTrial
figure(1);clf
pause(2+randi(4)/2)
text(.5,.5,'go','fontsize',32)
axis off
tic
waitforbuttonpress
reactiontime = toc
keypressed = get(gcf,'CurrentCharacter')
close(1)
end

Output 12.6.2:

reactiontime =
0.3626
keypressed =
x

Code 12.6.3:

function RunOneTrial
myfigure = figure(1);clf
pause(2+randi(4)/2)
text(.5,.5,'Press!','fontsize',32)
axis off
reactiontime = [];
tic
set(myfigure,'Keypressfcn',@gotAKey)
timedout = true;
pause(3)
close all;
% Other computation, such as recording the data
if timedout
    disp('timed out')
elseif correct
    fprintf('Reaction Time = %f\n',reactiontime)
else
    disp('It was an error')
    beep
end

    function gotAKey(src,event)
        timedout = false;
        if strcmp(event.Character,'g');
            reactiontime = toc;
            correct = true;
            set(myfigure,'Keypressfcn',[])
        else
           correct = false;
        end
    end

end

Output 12.6.3:

>> Code_12_5_3
Reaction Time = 0.749595
>> Code_12_5_3
timed out
>> Code_12_5_3
It was an error

Code 12.6.4:

function RunOneTrial
myfigure = figure(1);clf
pause(2+randi(4)/2)
text(.5,.5,'Press!','fontsize',32)
axis off
reactiontime = [];
tic
set(myfigure,'Keypressfcn',@gotAKey)
timedout = false;
mytimer = timer('TimerFcn', @timercallback, 'startDelay', 3);
start(mytimer)
wait(mytimer)
if timedout
    disp('timed out')
    beep
elseif correctresponse
    fprintf('Reaction time = %f\n',reactiontime);
else
    disp('error')
    beep
end
close(myfigure)
% ... Other computation, such as recording the data
return

    function gotAKey(src,event)
        correctresponse = false;
        if strcmp(event.Character,'g')
            reactiontime = toc;
            correctresponse = true;
        end
        timedout = false;
        stop(mytimer)
        set(myfigure,'Keypressfcn',[])
    end


    function timercallback(src,event)
        timedout = true;
    end

end

Code 12.6.5:

function SimonDemo;
clc
clear
close all;
sinit = input('Subject''s initials: ','s');
outfilename = ['SimonData_' sinit];
rawdataoutfilename = strrep(outfilename,'_','_Rawdata_');
rawdataoutfilename = strcat(rawdataoutfilename,'.txt');
rawdatafile = fopen(rawdataoutfilename,'w');
fprintf(rawdatafile,'Trial\tside\tstim\tcomp\tKey\tResp.\tRT\n');
screensize = get(0,'screensize');
% SetScreen
hfig = figure('position',[0 0 screensize(3) 200],'color', [1 1 1]);

% DefineTrialTypes
[ttype(1:4).side] = deal('L','R','L','R');
[ttype(1:4).stim] = deal('L','L','R','R');
[ttype(1:4).comp] = deal('C','I','I','C');

% InitializeData.
[ttype(1:4).RT] = deal([]);
[ttype(1:4).error] = deal(0);
%Run 8 blocks of the four types in random order (32 in all);
trialnumber = 0;
for blocknumber = 1:8
    for typenum = randperm(4);
        trialnumber = trialnumber + 1;
        pause(2)
        hfix = text(.5,.5,'+','fontsize',36);
        axis off
        set(gca,'position',[0 0 1 1])
        pause(1)
        % Run the trial
        if ttype(typenum).side == 'L'
            stimposition = .1;
        else
            stimposition = .9;
        end
        hstim = text(.1,.5,ttype(typenum).stim,'fontsize',...
                    72,'fontweight','bold');
        tic
        waitforbuttonpress
        % Record the response
        thisRT = toc;
        thechar = get(gcf,'CurrentCharacter');
        delete([hfix hstim]);
        switch thechar
            case 'a'
                thisResp = 'L';
            case ';'
                thisResp = 'R';
            otherwise
                thisResp = 'X'; % illegal key
        end
        if ttype(typenum).stim == thisResp
            ttype(typenum).RT = [ttype(typenum).RT thisRT];
            fprintf(rawdatafile,'%2d\t%s\t%s\t%s\t%s\tcorrect\t%5.2f\n',...
                 trialnumber,...
                 ttype(typenum).side,...
                 ttype(typenum).stim,...
                 ttype(typenum).comp, thisResp, thisRT);
        else
            ttype(typenum).error = ttype(typenum).error + 1;
            beep
                 fprintf(rawdatafile,'%2d\t%s\t%s\t%s\t%s\terror\t%5.2f\n',...
                 trialnumber,...
                 ttype(typenum).side,...
                 ttype(typenum).stim,...
                 ttype(typenum).comp, thisResp, thisRT);
        end
    end
end
    save(outfilename,'ttype');
    fclose(rawdatafile);

Code 12.6.6:

load SimonData_ef.mat
ttype
type1data = ttype(1)

Output 12.6.6:

ttype =
1x4 struct array with fields:
    side
    stim
    comp
    RT
    error
type1data =
     side: 'L'
     stim: 'L'
     comp: 'C'
       RT: [0.4938 0.6327 0.6572 0.8561 0.6182 0.7189 0.8305]
    error: 1

Code 12.6.7:

type SimonData_Rawdata_ef.txt

Output 12.6.7:

Trial   side stim comp Key    Resp.    RT
1 L    L    C    R    error  0.73
2 R    R    C    R    correct    0.79
3 L    R    I    R    correct    0.54
4 R    L    I    L    correct    0.51
5 L    R    I    R    correct    0.44
6 L    L    C    L    correct    0.49
7 R    L    I    R    error  0.39
8 R    R    C    R    correct    0.68
...data from 24 more trials not shown

Solutions

% Solutions_Chapter_12

% Solutions for selected problems from MATLAB for Behavioral Scientists,
% Second Edition (D. A. Rosenbaum, J. Vaughan, & B. Wyble),
% (c) 2015, Taylor & Francis

% To generate the solution for one problem, copy and run the code for that
% problem in a file or paste it into the Command window. Show the Command
% window to see the results.

% To generate sll the solutions for Chapter 12, save this code as a
% MATLAB script file and run the program.

% To execute Solution_12_7_1, download GUIDEexample_12_7_1_Folder.zip
% from the website, and run the program GUIDEexample_12_7_1.m from that
% folder, which must also contain GUIDEexample_12_7_1.fig.

% To execute Solution_12_7_2, you must copy and paste the code amd run it
% from the editor, because it interacts with the user.


function main % Problems in this chapter may have nested or local
% functions so the ProblemsChapter12 file must itself be a function
clc
commandwindow
close all
Solution_12_7_1 %Run each of the problem functions in turn.
Solution_12_7_2
Solution_12_7_3
Solution_12_7_4
Solution_12_7_5
Solution_12_7_6
end

% 12.7 Practicing user interactions

% Try your hand at the following exercises, using only the methods
% introduced so far in this book or in information given in the
% problems themselves.

% Problem 12.7.1

% Finish the interface implementing the callback routines in
% Guideexample_12.7_1.m, and Guideexample_12_7_1.fig, which you
% will generate using the example of Output.12.7.1 and GUIDE,
% by finding the callback routines in the code generated by GUIDE
% and inserting the appropriate code to respond to the user's actions.


function Solution_12_7_1

fprintf('A solution to problem 12.7.1 is in the script\n')
fprintf('   GUIDEexample_12_7_1.m\n\n')
fprintf('The figure file GUIDEexample_12_7_1.fig\n')
fprintf('   must be in the same folder as the script when it is run!\n\n')
fprintf('Both files can be downloaded from the file\n')
fprintf('   GUIDEexample_12_7_1_Folder.zip.\n\n')
fprintf('See Solution_12_7_2 for a related example of implementation\n')
fprintf('   of callback routines.\n\n')

end  %

% Problem 12.7.2

% Combine Code 7.3.6 with Code 12.4.3, to make a GUI-based
% program for computing the number of days in any month.
% Provide the output (e.g., 'February 2008 has 28 days')
% using an appropriate user control, in the same window as the input.

function Solution_12_7_2;
fprintf('\n\n          %s\n\n','Output 12.7.2')
fprintf('Function Solution_12_7_2 must be run from the editor because\n')
fprintf('it interacts with the user.\n\n');

% Most of this function is identical to Code 12.4.3; the implementation
% of the computation of days in the month has simply been added at the
% appropriate place, based on Code 7.3.6

% Initialize variables common to main and nested subfunctions
month = 'January';
year = 2001;
% Open the figure for the interface
handletothefigure = figure;
title('Output 12.7.2');
set(gca,'xticklabel',[]);
set(gca,'xtick',[]);
set(gca,'yticklabel',[]);
set(gca,'ytick',[]);
box on;
% Install a popup menu for the months
monthstrings = {
    'Month'
    'January'
    'February'
    'March'
    'April'
    'May'
    'June'
    'July'
    'August'
    'September'
    'October'
    'November'
    'December'};
hmonth = uicontrol('Style', 'popupmenu',...
    'String',monthstrings,...
    'Position', [120 320 100 20],...
    'Callback', @monthcallback);

% Install a popup menu for the years
hyear = uicontrol('Style', 'popupmenu',...
    'String',...
    'Year|2008|2009|2010|2011|2012|2013|2014|2015|2016|2017|2018',...
    'Position', [220 320 100 20],...
    'Callback', @yearcallback);

% Install an informative text field for the popup controls
uicontrol('Style','text','String','Pick a month and a year: ',...
     'Position', [120,360,200,15]);

% Install a GO button
hgobutton = uicontrol('Style','pushbutton',...
    'String','Look up days in the month',...
    'Position', [120 120 200 40],...
    'Callback', @gobuttoncallback);

return % from main

% Callback routines in nested functions:
    function monthcallback(source,eventdata)
        mylist = (get(source,'String'));
        myitem = (get(source,'Value'));
        month = char(mylist(myitem))
    end

    function yearcallback(source,eventdata)
        mylist = (get(source,'String'));
        myitem = (get(source,'Value'));
        year = str2num(mylist(myitem,:))
    end

    function gobuttoncallback(source,eventdata)
        hmsg = msgbox(sprintf(...
          'Will compute days for %s, %d\n\n',month, year));
        uiwait(hmsg)
% Code from Code 7.3.6 goes here, to compute the days in the month
% Executed as part of the GOBUTTONCALLBACK routine.
% Days_In_A_Month
% Month and year have already been specified in the pulldown menu
%    callback routines.
% month = input('Type in the month: ','s');
% year = input('Type in the year (4 digits): ');
switch month
    % Thirty days hath September,
    % April, June, and November...
    case {'September' 'April' 'June' 'November'}
        no_of_days = 30;
    case 'February'
        if rem(year, 4) == 0 & ...
                (rem(year, 100) ~= 0 | rem(year, 400) == 0)
            no_of_days = 29;
        else
            no_of_days = 28;
        end
        % All the rest have thirty-one
    otherwise
        no_of_days = 31;
end
fprintf('%s %d has %d days.\n', month, year, no_of_days);
hmsg = msgbox(sprintf(...
    '%s %d has %d days.\n', month, year, no_of_days));
uiwait(hmsg)
close(handletothefigure)
    end

end %function Solution_12_7_2

% Problem 12.7.3

% Using uicontrol or GUIDE, devise an appropriate user
% interface for a program that you have previously written.

function Solution_12_7_3
fprintf('\n\n          %s\n','Output 12.7.3')
fprintf('Solution left to the student.\n\n');
end % function Solution_12_7_3

% Problem 12.7.4

% Write a program to analyze the file SimonData_Rawdata_ef.mat
% from the web site (or your own data file from running
% Code 12.6.5, or a similar tab-delimited text file of your
% choosing) and report the reaction times for the four
% conditions. Make the output suitable for transfer to a
% spreadsheet or statistics program.

function Solution_12_7_4
fprintf('\n\n          %s\n','Output 12.7.4')
fprintf('Solution left to the student.\n\n');
end % function Solution_12_7_4

% Problem 12.7.5

% Write a program to analyze the file SimonData_Rawdata_ef.txt
% from the web site (or your own data file from running Code
% 12.6.5, or a similar tab-delimited text file of your choosing)
% and report the reaction times for the four conditions. Make
% the output suitable for transfer to a spreadsheet or
% statistics program. Do the results agree exactly with those
% of Problem 12.7.4? Should they? (See Section 7.6 to help you
% get started).

function Solution_12_7_5
fprintf('\n\n          %s\n','Output 12.7.5')
fprintf('Solution left to the student.\n\n');
end % function Solution_12_7_5

% Problem 12.7.6

% Present a brief tone of moderate intensity, and allow the
% user to raise or lower the intensity of the tone using the
% up-arrow and down-arrow keys of the keyboard. Instruct the
% user to lower the intensity for the next trial if she hears
% it, and raise the intensity if she does not. Plot the
% psychophysical absolute threshold determined in this way,
% using a staircase graph. Make it possible to vary the frequency
% of the test stimulus. (If you'd like, use a patch of grey
% on a dark grey background, instead, and plot the difference
% threshold as the patch is adjusted brighter and darker. Vary
% the brightness of the background on different trials, and
% determine the ratio between the difference threshold and the
% brightness of the background.)  Consider what precautions
% should be taken to ensure that performance is not affected
% by non-sensory factors such as stimulus sequence.

function Solution_12_7_6
fprintf('\n\n          %s\n','Output 12.7.6')
fprintf('Solution left to the student.\n\n');
end % function Solution_12_7_6

A solution to problem 12.7.1 is in the script

GUIDEexample_12_7_1.m

The figure file GUIDEexample_12_7_1.fig

must be in the same folder as the script when it is run!

Both files can be downloaded from the file

GUIDEexample_12_7_1_Folder.zip.

See Solution_12_7_2 for a related example of implementation of callback routines.

Output 12.7.2:

Function Solution_12_7_2 must be run from the editor because
it interacts with the user.
Output 12.7.2

Output 12.7.3

Solution left to the student.

Output 12.7.4:

Solution left to the student.

Output 12.7.5

Solution left to the student.

Output 12.7.6:

Solution left to the student.