解説1

ここでは、実験の前準備について説明をします。

function results = MullerLyerIllusion(subID)

function名のMullerLyerIllusionの後に(subID)とあります。これはMullerLyerIllusion関数が入力引数を1つとって、その値をsubIDという変数に代入することを意味しています。Matlabのコマンドウィンドウで

MullerLyerIllusion(12)

のように入力することにより、実験参加番号12番の人のデータを記録することができます。このとき出力ファイル名は、MLIexpSubj12.txtとなります。コマンドウィンドウで、

MullerLyerIllusion

として実行したり、Matlabエディタで実行した場合には、subIDは自動的に66になります。(どうしてデフォルトの値を66なんて中途半端な数字にしたんだろう・・・)

if ~exist('subID','var')
    subID=66;
end

exist関数を使って、変数subIDが存在しているかを確認しています。上述のようにコマンドウィンドウで

MullerLyerIllusion(12)

とすると、自動的にsubIDに12が代入されます。このときexist('subID','var')は1を返します。さらにexistの前にチルダがついているので、exist関数の結果が反転し0になります。この結果if文の中身は実行されません。つまりsubIDは12のままです。

MullerLyerIllusion

として実行した場合には、変数subIDは存在していないのでexist('subID','var')の結果は0となり、それが反転してif文の中身が実行されます。つまり、subIDに66が代入されます。

%warn if duplicate sub ID
fileName=['MLIexpSubj' num2str(subID) '.txt'];
if exist(fileName,'file')
    if ~IsOctave
        resp=questdlg({['the file ' fileName 'already exists']; 'do you want to overwrite it?'},...
            'duplicate warning','cancel','ok','ok');
    else
        resp=input(['the file ' fileName ' already exists. do you want to overwrite it? [Type ok for overwrite]'], 's');
    end
   
    if ~strcmp(resp,'ok') %abort experiment if overwriting was not confirmed
        disp('experiment aborted')
        return
    end
end

コメントに書かれているようにsubIDが以前に行った実験のsubIDと重複していたら警告を出します。つまり、実験が終わるごとにsubIDを含んだファイルが出力されますので、同じsubIDの実験参加者のデータを取ると、前のデータが上書きされるわけです。

出力ファイル名は、MLIexpSubj12.txtとなります(subIDが12の場合)。num2strで数字を文字列のデータに変換します。

IsOctaveというのは、実験プログラムをOctave上で動かしているのかどうかを調べる関数です。Matlabで動かすときと、Octaveで動かすときとで、使用できる関数に違いがあるようですね。プログラムを動かす環境が固定されているのであれば、あえてIsOctaveを使って場合分けをする必要はありません。

questdlgを使用すると、実験参加者にYesかNoで答えるような質問をすることができます。回答の結果が変数respに代入されます。

strcmpで、変数respの内容がokと一致するかどうか(つまり上書きしてよいか)を調べています。respがokでなければ、'experiment aborted'を返してプログラムを中断します。

condtable

Matlabでの重要な概念である行列の構造になっています。といっても難しいことはなく、縦と横に数字を並べているだけです。

各行が1試行に対応しています。

各列が実験条件に対応しています。1列目と2列目が線分の長さ、2列目と3列目が矢羽の向き、を表しています。

ntrials=size(condtable,1);

condtableの行数がntrialsに代入されます。上述のように各行は1試行に対応していますから、行数が全試行数になるわけです。ちなみにsize(condtable,2)は列数を表し、4となります。

shuffeldTrialIDs=randperm(ntrials);

randpermは1からntrials (=16) までの数字をランダムに並べ替えます。ブレークポイントを設定してデバッグしてみると、shuffeldTrialIDsの値は [5, 2, 6, 14, 4, 9, 8, 12, 11, 7, 16, 15, 1, 10, 13, 3] のようになっていました。shuffeldTrialIDsの値は、実験をするたびに変わります。randpermを使うことによって、実験参加者ごとにランダムな順番で刺激を呈示することが可能になるのですね。

ntrain=3;

練習試行の回数です。

order=[ceil(rand(1,ntrain)*ntrials), shuffeldTrialIDs];

少し複雑な表現ですが、1つひとつ見ていけば難しくはありません。まずrand(1,ntrain)ですが、ntrainは3なのでrand(1, 3)と同じです。1行3列のランダムな数字が返ります。Matlabのコマンドウィンドウでrand(1, 3)を実行するのが一番分かりやすいでしょう。結果が0から1の小数になっていることに注意してください。

rand(1, 3)にntrials(=16)をかけます。例えばその結果 [7.0829, 1.7064, 15.3904] となったとしましょう。

ceilは小数の値を整数にするのですが、いわゆる切り上げを行います。上の例の場合、[8, 2, 16] となります。この行ベクトルshuffeldTrialIDsをくっつけて、orderという新しい行ベクトルにします。

つまり何をしたかったというと、全16試行の実験の前に3試行の練習があって、その3試行分の条件をランダムに選んできているわけです。条件8と2と16が練習試行となります。

colHeaders

出力結果の上部に記述するものです。出力結果の各列が何を意味しているのかを分かりやすくするためのものです。

results=NaN * ones(length(order),length(colHeaders)); %preallocate results matrix

コメントに書いてあるように、事前に出力結果を保存する行列を作っておきます。

NaNは Not a Number(不定値)の略です。

onesはすべての要素が 1 の行列を作成します。例えばones(2, 3)とすると、2行3列の行列ですべての要素が1の行列ができます。ここでは、行の数がlength(order)で、列の数がlength(colHeaders)になります。length(order)は19(練習試行3+本試行16)で、length(colHeaders)は11です。

つまり、19行11列の配列ができて、すべての要素はNaNとなります。

lw=3;

ミュラーリヤーの線分の幅です。Line Widthの略と思われます。

解説1はここまで。