.. _chapter-basic-experiment: 最初の実験を作ってみよう―サイモン効果 ======================================================================= 実験の手続きを決めよう ------------------------------- この章では、最初の実験としてサイモン効果の実験を作ってみましょう。サイモン効果について詳しい解説は認知心理学の教科書などを参考にしていただくとして、ここでは実験の手続きを説明します。 .. _fig-simon-effect: .. figure:: fig03/simon-effect.png :width: 80% サイモン効果の実験概要。実験参加者は刺激の色に対応するキーをできるだけ速く正確に押すように求められます。スクリーン上の刺激の位置と反応するキーの位置関係が反応の速さや正確さに及ぼす影響を検討します。 :numref:`fig-simon-effect` をご覧ください。実験参加者に与えられた課題は、PCのスクリーン上に提示された刺激の色に応じて、PCのキーボードのキーを指定された指で押すことです。参加者はスクリーン中央の十字(固視点)に視線を向けて、刺激が出現するのを待ちます。刺激は赤色または緑色の円で、固視点の右側または左側のどちらかに出現します。参加者は刺激の色が赤色であれば左手の人差し指でxのキー、緑色であれば右手人差し指で / (スラッシュ)のキーをできるだけ速く、間違わないように押さないといけません。左側に赤色の刺激が出現した場合と右側に緑色の刺激が出現した場合には刺激と反応する指が同じ側になりますが、それ以外の場合は刺激が出現した側と反対側の指で反応しないといけません。刺激が提示される位置と反応する指の関係が反応の速さや正確さにどのように影響するかを確認しようというわけです。 さて、実際に実験を作成するためには、 :numref:`fig-simon-effect` の内容よりもっと詳細に手続きを決定する必要があります。 :numref:`fig-simon-effect-procedure` は刺激提示スクリーンの時間的な変化を図示したものですが、このように書いてみると :numref:`fig-simon-effect` の内容ではx1からx5の値が決まっていないことがわかります。何かの文献に基づいて実験を作成しているのであれば文献に書かれている手続きを熟読して値を決めることになるでしょう。この章では、あまり内容を高度にし過ぎないためにあらかじめ以下のように値を決めることにします。 - x1 固視点の大きさは縦横0.05(位置と大きさの単位はすべてheight)。 - x2 試行が始まってから刺激が出現するまでの時間は1.0秒。 - x3 固視点の中心から刺激の中心までの距離は0.7。 - x4 刺激の直径は0.1。 - x5 刺激の位置(2か所)と色(2種類)の組み合わせで合計4種類の刺激に対して25試行ずつ、合計100試行。 .. _fig-simon-effect-procedure: .. figure:: fig03/simon-effect-procedure.png :width: 80% サイモン効果実験の手続き。実際に実験を作成するためにはx1からx5の値を決定する必要があります。 刺激はスクリーンの左右端付近に出したいのですが、使用するスクリーンの縦横比によって左右端のX座標が異なります。ここでは縦横比3:2のスクリーンでも刺激がおさまることを考えて固視店の中心から刺激の中心までの距離(x3)を0.7、刺激の直径(x4)を0.1としました。この辺りの数値は各自の実行環境に応じて変更してください。 実験を作成する前にもうひとつ確認して置きたいのは、この実験において「試行毎に変化する値」は何かという点です。 :numref:`fig-simon-effect` から明らかなように、刺激の色(赤or緑)と刺激の位置(右or左)は試行毎に変化します。刺激の色が変化するという事は、それに対応して正解となるキー(x or /)も変化することに注意しましょう。 さて、それではいよいよ実験の作成を始めましょう。なお、今回作成する実験のpsyexpファイル名は、第3章の実験ということでexp03.psyexpとすることにします。 視覚刺激を配置しよう --------------------------------- :numref:`第%s章 ` では視覚刺激の大きさや位置、色の指定などについて学んだのですから、まずは刺激の作成から始めましょう。まず、刺激の円はPolygonコンポーネントで **[形状]** を円すれば描画できます。 刺激の位置と色は試行毎に変化しますが、まだその方法は解説していませんのでひとまず(0.7,0)の位置に赤色で表示することにしましょう。Polygonコンポーネントをひとつルーチンに配置し、以下のように設定してください。 - 「基本」タブ - **[名前]** にstimulusと入力する。 - **[形状]** を円にする。 - 「外観」タブ - **[塗りつぶしの色]** にred、**[枠線の色]** にNoneと入力する。 - 「レイアウト」タブ - **[位置 [x, y] $]** に(0.7, 0)と入力する。 - **[サイズ [w, h] $]** に(0.1, 0.1)と入力する。 - PsychoPyの設定でheight以外の単位を標準に設定している場合は、実験設定ダイアログを開いて **[単位]** をheightにしておく。 続いて固視点ですが、幸いなことにPolygonコンポーネントは十字を描くこともできます。新たにPolygonコンポーネントを1つルーチンに配置し、以下のように設定してください。 - 「基本」タブ - **[名前]** にcrossと入力する。 - **[形状]** を十字にする。 - 「レイアウト」タブ - **[サイズ [w, h] $]** に(0.05, 0.05)と入力する。 続いて提示時間の設定について考えましょう。試行開始時には固視点のみがスクリーン上に提示されていて、試行開始1.0秒後に刺激が提示されるのですから、固視点(cross)の **[開始]** は「時刻 (秒)」で0.0、刺激(stimulus)の **[開始]** は「時刻 (秒)」で1.0にすればよいでしょう。固視点、刺激ともにキーが押されるまでずっと提示されるのですから、 **[終了]** はどちらも空白にしておきましょう。 さて、ここまでの作業を終えると、ルーチンペインには :numref:`fig-put-stim-cross` 上のように2つのPolygonコンポーネントが並んでいるはずです。コンポーネントの順番はこの通りでなくても構いません。そして実験を実行すると :numref:`fig-put-stim-cross` 下のようにスクリーンに刺激が提示されることを確認してください。ここまでの記述で分からないことがあったら :numref:`第%s章 ` を復習してください。ここまで確認できればいよいよキーボードを用いて実験参加者の反応を検出する方法を学びましょう。 .. _fig-put-stim-cross: .. figure:: fig03/put-stim-cross.png :width: 80% 視覚刺激用のPolygonコンポーネントの配置と実行確認。 チェックリスト - Polygonコンポーネントを用いて円をスクリーン上に提示することができる。 - Polygonコンポーネントを用いて十字をスクリーン上に提示することができる。 キーボードで反応を検出しよう -------------------------------------------- Builderからキーボードを利用するには、コンポーネントペインのResponseというカテゴリに含まれるKeyboardコンポーネントをルーチンペインに配置します。PolygonやTextコンポーネントを配置する時と同じように、コンポーネントペインのKeyboardコンポーネントのアイコン( :numref:`fig-keyboard-icon` )をクリックしましょう。するとKeyboardコンポーネントのプロパティ設定ダイアログが開きます。 .. _fig-keyboard-icon: .. figure:: fig03/keyboard-icon.png :width: 80% Keyboardコンポーネントのアイコン 「基本」タブの **[名前]** 、 **[開始]** や **[終了]** は、 :numref:`第%s章 ` で扱ったコンポーネントと同様に、名前をつけたりコンポーネントが有効となる時間を指定したりするために使用します。視覚刺激の場合、「有効となる時間」はスクリーン上に表示されている時間に対応しましたが、Keyboardコンポーネントの場合はキー押し反応を受け付ける時間に対応します。例えば今回の実験の場合、刺激がスクリーン上に出現する前に押されたキーは無視するべきですから、試行開始1.0秒経過するまでKeyboardコンポーネントは無効にするべきです。また、今回は参加者が反応するまで待ち続けますが、実験によっては3秒以内に反応できなかったら強制的に次の試行に移るといったこともあるでしょう。 **[開始]** と **[終了]** を適切に設定することによってこういった実験を実現することができます。 **[終了]** の下に **[Routineを終了]** という項目がありますが、ここにチェックが入っていれば、キーが押されると他のコンポーネントがまだ終了していなくても強制的にルーチンを終了します。今回はこの機能を利用して「参加者がキーを押すまで刺激を提示し続ける」という動作を実現します。仮に「30秒間スクリーンを注視し、刺激が無作為な時間間隔で複数回スクリーン上に出現する度にできるだけ速くキーを押す」といった実験の場合はキーが押されてもルーチンを中断してはいけません。このような実験の場合は **[Routineを終了]** のチェックを外しておきます。 **[検出するキー $]** には、Builderがキー押しを監視するキーの名前を列挙します。初期状態では'y', 'n', 'left', 'right', 'space'と入力されています。これは順番にアルファベットのYキー、Nキー、カーソルキーの「←」キー、「→」キー、スペースキーを表すキー名です。必ず半角文字で入力すること、キー名の前後にシングルクォーテーションまたはダブルクォーテーション記号でキー名を囲むこと、キー名の間はカンマで区切ることが重要なポイントです。ここに書かれたキー以外が押された場合は、Keyboardコンポーネントが有効な時間帯であっても無視されます。参加者が反応に使用するキーのみを書くことによって、参加者が誤って無効なキーを押してしまってルーチンが終了してしまうことを防止できます。心理学実験ではあまり無いことだと思いますが、すべてのキーを有効する必要がある場合は **[検出するキー $]** を空白にしてください。 問題は自分が使いたいキーのキー名を何と書けばよいのかですが、一般的な日本語キーボードであれば :numref:`tbl-ja-key-names` に示すキー名が使えるはずです。一般的な日本語キーボードではShiftキーを押しながら1キーを押すと ! 記号を入力できますが、PsychoPyは ! というキーが押されたとは判断せず、あくまでShiftと1キーが押されたと判断しますので注意してください。 もうひとつ注意しないといけない点は、キーボードによっては特殊キーの左右を区別しないなどのクセがある点です。例えば :numref:`tbl-ja-key-names` では左シフトキーと右シフトキーにそれぞれlshift、rshiftという名前が割り当てられていますが、使用しているキーボードが左右どちらのキーを押してもlshiftというキー名を返すように作られている場合があります。自分が使用する予定のキーボードがどのようなキー名を返すのか確認したい、Windows用キーボードのWindowsキーやMac用キーボードのCommandキーがどのような名前を返すのか確認したいといった場合は、キー名を表示させるBuilderの「実験」を作成すると便利です。作成にはずっと先の章で取り上げる予定のテクニックが必要になりますので、ここでは扱わず「 :numref:`{number}:{name} ` 」に記しておきました。 .. _tbl-ja-key-names: .. csv-table:: 一般的な日本語キーボードで使用できるキー名 :header: "キー名", "対応するキー", "キー名", "対応するキー" **f1**, F1, **minus**, \- **f2**, F2, **asciicircum**, ^ **f3**, F3, **backslash**, \\ **f4**, F4, **bracketleft**, [ **f5**, F5, **bracketright**, ] **f6**, F6, **semicolon**, ; **f7**, F7, **colon**, : **f8**, F8, **comma**, "," **f9**, F9, **period**, . **f10**, F10, **slash**, / **f11**, F11, **at**, @ **f12**, F12, **return**, Enterキー **num_0**, 0 (テンキー), **1**, 1 **num_1**, 1 (テンキー), **2**, 2 **num_2**, 2 (テンキー), **3**, 3 **num_3**, 3 (テンキー), **4**, 4 **num_4**, 4 (テンキー), **5**, 5 **num_5**, 5 (テンキー), **6**, 6 **num_6**, 6 (テンキー), **7**, 7 **num_7**, 7 (テンキー), **8**, 8 **num_8**, 8 (テンキー), **9**, 9 **num_9**, 9 (テンキー), **0**, 0 **num_add**, \+ (テンキー), **a**, A **num_subtract**, \- (テンキー), **b**, B **num_multiply**, \* (テンキー), **c**, C **num_divide**, / (テンキー), **d**, D **num_decimal**, . (テンキー), **e**, E **left**, ←, **f**, F **down**, ↓, **g**, G **right**, →, **h**, H **up**, ↑, **i**, I **escape**, ESCキー, **j**, J **pageup**, PageUpキー, **k**, K **pagedown**, PageDownキー, **l**, L **end**, Endキー, **m**, M **home**, Homeキー, **n**, N **delete**, Delキー, **o**, O **insert**, Insキー, **p**, P **backspace**, バックスペースキー, **q**, Q **tab**, タブキー, **r**, R **lshift**, 左シフトキー, **s**, S **rshift**, 右シフトキー, **t**, T **lctrl**, 左Ctrlキー, **u**, U **rctrl**, 右Ctrlキー, **v**, V **lalt**, 左Altキー, **w**, W **ralt**, 右Altキー, **x**, X , , **y**, Y , , **z**, Z 説明も長くなってきましたので、その他の項目は後で解説することにして、まずは動作を確認してみましょう。Keyboardコンポーネントのプロパティ設定ダイアログで以下のように設定してください。 - 「基本」タブ - **[開始]** を「時刻 (秒)」にして1.0と入力する。 - **[終了]** を空白にする。 - **[Routineを終了]** にチェックが入っていることを確認する。 - **[検出するキー $]** に 'x', 'slash' と入力する。 - その他の項目は初期設定のままにする。 .. _fig-keyboard-settings: .. figure:: fig03/keyboard-settings.png :width: 80% Keyboardコンポーネント配置後のルーチン。反応に関するコンポーネントの有効な時間はオレンジ色のバーで表示されます。 これらの設定が済めばルーチンペインは :numref:`fig-keyboard-settings` のようになるはずです。Keyboardコンポーネントの有効な時間を示すバーが青ではなくオレンジである点に注意してください。反応計測に用いるコンポーネントはこのようにオレンジ色で表示されます。これで、xまたは / キーが押されたことを検出してルーチンを終了させることができるようになりました。以下のことを必ず確認しておいてください。 - 刺激(赤い円)が出現した後にxキーまたは / キーを押すと刺激提示が終了すること。 - 刺激(赤い円)が出現する前にxキーまたは / キーを押しても刺激提示が終了しないこと。 - xキー、 / キー、ESCキー以外のキーを押しても効果がないこと(ただしWindowsキーなどOSにより特殊な役割を持つキーは除く)。 キー押しが検出できたら次はそれをファイルに記録する方法をマスターしたいところですが、それはひとまず置いておいて、次節では刺激の位置や色を変更しながら試行を繰り返す方法を学びます。 チェックリスト - ルーチン実行中にキー押しが有効となる時間帯を指定できる。 - キーが押されると直ちにルーチンを中断するように設定することができる。 - 有効とするキーを指定できる。 - すべてのキーを有効にするように設定することができる。 条件ファイルを作成しよう ------------------------------------------- 今までは「実験」と言いつつただ静止画像が一回スクリーンに表示されて終了するだけでしたが、本節からいよいよ実験らしくなってきます。Builderでは、条件ファイルと呼ばれるファイルから試行毎の刺激の色や反応に使用できるキーなどの値を読み込んで設定する機能があります。この機能を用いることによって、今までは不可能だった「刺激の色や位置を変えながら試行を繰り返す」ことが可能になります。条件ファイルの作成方法は何通りかあるのですが、ここではExcelを用いた方法を解説します。第1章で述べたとおり、Excelをお持ちでない方はLibreOffice Calcを代わりに用いることができます。 では、条件ファイルの作成を始めましょう。Builderを一旦離れてExcelを起動してください。Builderで利用できる条件ファイルをExcelで作成するには、Excelのシートの各列に刺激の色や位置等のパラメータを割り当てて、実験で使用するパラメータの組み合わせを1条件1行で列挙します。 :numref:`fig-edit-conditions-file` を参考にしながら具体的に手順を追っていきましょう。 .. _fig-edit-conditions-file: .. figure:: fig03/edit-conditions-file.png :width: 80% 条件ファイルの作成。 今回の実験では試行毎に刺激の「色」と「位置」が変化します。このように変化していくものそれぞれにExcelの列を割り当てていきます。例えば「色」を1列目、「位置」を2列目に割り当てるとしましょう。このように、条件ファイルを通じて変化させていく値をパラメータと呼びます。この用語は以後頻出しますので覚えておいてください。続いて決めないといけないのは、それぞれのパラメータの「名前」です。人にものを頼む時には「コレをアレに載せといてよ」と言っても通じるかも知れませんが、コンピュータに作業を頼むときには「コレ」や「アレ」を曖昧さなしに示す必要があります。そこで用いられるのが名前です。「刺激の色」と言った時に「刺激」とは具体的にどのコンポーネントを指しているのか、「値を設定する」と言った時に「値」とはどこに記されているものか、といったことをコンピュータにもわかるように示すために、私たちがコンピュータに指示を出す時には、操作や参照の対象となるものすべてに固有の名前をつけなければいけません。「固有の名前」とは、言い換えると異なるものに同じ名前を割り当ててはいけないということです。:numref:`第%s章 ` でPolygonコンポーネントを複数配置した時に、一つ目のPolygonコンポーネントの **[名前]** の初期値が「polygon」、二つ目のPolygonコンポーネントの **[名前]** の初期値が「polygon_2」になっていたのに気付かれた方がおられると思いますが、これはBuilderが二つのPolygonコンポーネントを明瞭に **[名前]** で区別できるように自動的に異なる名前を割り振ってくれた結果なのです。 Builderで使用できる名前は、「Pythonの変数として使用できる名前」のうち、PsyhcoPyやBuilderでまだ使用されていないものに限られます。現在のPsychoPyのベースとなっているPython3では日本語の文字や一部の記号も名前に使用できるのですが、Pythonの文法規則の詳細を知らなければ理解しがたい制限も多いので、以下のルールを満たすものを使用するのが無難でしょう。 - 1文字目が英文字(A-Z、a-z)であること。アンダーバー( \_ ) も使用できるがアンダーバーから始まる名前は避けた方がよい。英文字の大文字と小文字は区別される。 - 2文字目以降が英文字(A-Z、a-z)またはアンダーバー( \_ )であること。英文字の大文字と小文字は区別される。 - Pythonの正常な動作のために確保されているキーワード(if, else, while, for, from, globalなど)やPsychoPyのモジュール名(core, data, visual, eventなど)、Builderの予約語(expInfo, expName, buttonsなど)は使用できない。以後、記述の簡略化のためにこれらを合わせて「予約語」と呼ぶ。 一番目と二番目の条件を満たすのはそれほど難しくありませんが、最後の「予約語を使用してはいけない」という条件は厄介です。予約語はPythonやBuilderが正常に動作するようにすでに使用している名前のことであり、かなりの数の名前が予約済みなので覚えるのはあまり現実的ではありません(「 :numref:`{number}:{name} ` 」参照)。予約語を避けるのに有効なのが、英小文字から始まる接頭語+アンダーバーという名前を用いるという方法です。例えば自分で決める名前すべて先頭にmy\_ を付けたり、刺激にはs\_、反応にはr\_を付けたりするといったルールを決めておけば、ほぼ確実に予約語を避けることができます。Builderを起動中であれば「 :numref:`{number}:{name} ` 」で述べる方法を用いてBuilderで使用できる名前を判別することができます。 本題に戻りましょう。今回は刺激の色と位置を変化させる必要がありますので、二つの名前を自分で決める必要があります。上記の名前に使える文字列の制限に加えて、作成中のルーチンペインにすでに配置済みのコンポーネントの **[名前]** と重複しないように名前を決める必要があります。ここでは色に対応する名前として stim_color、位置に対応する名前としてstim_xposという名前を使うことにしましょう。Excelの1行目にこれらの名前を入力してください。 名前を決めたら、次はそれぞれのパラメータの値を列挙していきます。値はBuilderが理解できるものでなければいけません。例えば「赤」とか「緑」とか日本語で入力してもBuilderは理解できませんので、:numref:`第%s章 ` で覚えたようにredやgreenとか#FF0000、#00AA00などと書かねばなりません。ややこしいことに$[1, 0, 0]などの表記は$を付けずに[1, 0, 0]と書かないといけないのですが、その理由は本章の「 :numref:`{number}:{name} ` 」で説明します。刺激の位置も「右」、「左」ではなく刺激の **[位置 [x, y] $]** にそのまま記入できる値を書く必要があります。 .. _fig-writing-conditions: .. figure:: fig03/writing-conditions.png :width: 80% パラメータの組み合わせを全て提示するか、特定の組み合わせだけを提示するかによって条件ファイルの書き方が異なります。 これらの注意点を念頭に置いて、まず刺激の色を入力しましょう。刺激の色は赤または緑ですから、stim_colorにはredとgreenを挙げる必要があります。これらの値を、stim_colorと入力したセルの下へ、空白セルを間に挟まずに並べていきます。続いて刺激の位置ですが、今回の実験では位置のY座標は変化しないのでX座標の値だけを列挙することにしましょう。固視点から刺激への距離を0.7に決めているのですから、左は-0.7、右は0.7です。stim_colorと同じようにstim_xposの列に-0.7、0.7を縦に並べればよいのですが、今回の実験では「赤」の刺激が「右」と「左」、「緑」の刺激が「右」と「左」で合計4通りの条件があることに注意しなければいけません。条件ファイルでは1行が一つの実験条件に対応しますので、これら4通りの条件がすべて列挙されなければいけません。どうすればよいかというと、stim_colorの列をred, red, green, greenといった具合にredとgreenが2回ずつ出現するように書き換えて、stim_xposに-0.7、0.7、-0.7、0.7と書けばよいのです( :numref:`fig-writing-conditions` 左)。これですべての条件が挙げられたことになります。この並べ方はBuilderで実験を作成する際には非常に頻繁に用いますのでよく覚えておいてください。なお、「赤色の時は必ず右に、緑色の時は必ず左に刺激が出現する」という実験の場合には2通りしか組み合わせがありませんので、 :numref:`fig-writing-conditions` 右のようにredと0.7、greenと-0.7がそれぞれ同一の行に並ぶように書きます。 今回の実験のパラメータには、刺激の位置と色の他にも「正解となる反応」がありますが、まずは実際に刺激が次々と提示される様子を確認することにしましょう。他のセルに不必要な値が入力されていないのを確認してから、作成したシートをExcelの「ブック(\*.xlsx)」形式で保存してください。以後、この形式で保存されたファイルをxlsxファイルと呼びます。保存するファイル名は、第3章の実験用の条件ファイルという事でexp03_cnd.xlsxとしておきます。LibreOffice Calcを使っている場合は標準ではxlsxファイルとして保存されませんので保存ダイアログの「ファイルの種類」からxlsx形式を選択することを忘れないようにしてください( :numref:`fig-save-conditions-file` )。 これで条件ファイルの準備ができました。Builderに戻ってこの条件ファイルを読み込むように実験を拡張しましょう。 .. _fig-save-conditions-file: .. figure:: fig03/save-conditions-file.png :width: 70% 条件ファイルをExcelのブック(\*.xlsx)形式で保存します。Excelの場合は標準でxlsxファイルとして保存されますが、LibreOffice Calcの場合は[ファイルの種類]からxlsx形式を選択する必要があります。 チェックリスト - ExcelまたはLibreOffice Calcを用いて、実験に用いるパラメータを列挙した条件ファイルを作成することができる。 - 実験のパラメータを表現するためにPsychoPyで使用できる名前を決めることができる。 .. _section-insert-loop: 繰り返しを設定しよう ------------------------------- Excelは一旦終了して、Builderに戻ってください。一度Builderを終了してしまった人はexp03.psyexpを開きましょう。開いたら、ルーチンペインの下のフローペインを見てください。 :numref:`fig-insert-loop` の左上のように、左から右に矢印が描かれていて、矢印の上にtrialと書かれた四角いアイコンが描かれています。フローペインは実験の流れ(フロー)を示しており、左から右へ向かって実験が進行します。trialと描かれた四角はルーチンを示しており、trialルーチンは実験を作成すると自動的に作成されるルーチンです。ここまでの作業で「ルーチンにコンポーネントを配置する」という作業を何度も繰り返しましたが、これらの作業はいずれもtrialルーチンに対して行っていたのです。 .. _fig-insert-loop: .. figure:: fig03/insert-loop.png :width: 80% 繰り返しの挿入。 さて、このtrialルーチンを繰り返し実行するためには、フローにループを挿入する必要があります。ループを挿入するには、フローペインの左端の「ループを挿入」を左クリックします。クリックした後にフロー上にマウスカーソルを動かすと、ループの始点または終点を挿入できる点にカーソルが重なった時にその場所に黒い円が表示されます( :numref:`fig-insert-loop` 左下)。黒い円が表示されている時にその位置をクリックすると、始点または終点として指定することができます。通常は始点と終点の二カ所を指定する必要がありますが、今回はルーチンが一つしかなくて始点が決まると終点は自動的に決まってしまうため、一カ所をクリックするだけで始点と終点が確定します。 ループの始点と終点が確定すると、ループの設定ダイアログが表示されます。ここではループの名前や種類、ループ回数、条件ファイルなどを指定します。名前はコンポーネントの名前と同様に、Builder上での表示をわかりやすくするためなどに使えます。問題は **[Loopの種類]** ですが、本章では指定できる種類の内sequential、random、fullRandomの三種類を解説します。残りの2つは :numref:`第%s章 ` を参照してください。 :numref:`fig-loop-types` は、exp03_cnd.xlsxで指定した4条件の条件ファイルをsequential、random、fullRandomで繰り返した場合の実行例を示しています。ループ回数を指定する **[繰り返し回数 $]** には3が入力されていると仮定しています。sequentialでは、条件ファイルに書かれた条件が、そのままの順番で2行目(1行目はパラメータ名)から実行されます。最後の行まで進むとまた2行目に戻って繰り返し、 **[繰り返し回数 $]** で指定された回数の繰り返しが終了すると終了します。randomとfullRandomでは無作為に順番が並べ替えられますが、randomでは「条件ファイルに書かれた条件を無作為に並び替えて実行する」という作業を **[繰り返し回数 $]** 回繰り返します。従って、それぞれのループでは条件ファイルに書かれた条件が必ず1回ずつ実行されます。 :numref:`fig-loop-types` のrandomの例で1回目、2回目、3回目の繰り返しの全てにおいて条件ファイルに書かれた4つの条件が1回ずつ実行されていることを確認してください。これに対して、fullRandomでは全試行を終えた時点で条件ファイルに書かれた条件がそれぞれ **[繰り返し回数 $]** 回繰り返されます。 :numref:`fig-loop-types` のrandomとfullRandomをよく見比べてその違いを理解してください。一般論として、randomでは同一条件の試行が続くことはあまりありません(n回目の繰り返しの最後の試行とn+1回目の繰り返しの最初の試行が一致した場合のみ)が、fullRandomでは同一条件の試行が続くことがしばしばあります。これらのループタイプを使い分けることがBuilderを使いこなすコツです。 .. _fig-loop-types: .. figure:: fig03/loop-types.png :width: 70% 3種類のループタイプの違い。 **[乱数のシード $]** は、繰り返し順序の無作為にするための処理を操作するための項目です。 **[乱数のシード $]** を空白にしておくと、PsychoPyが実験を実行する度に異なる繰り返し順序を決定してくれます。しかし、例えば498202という整数を指定しておくと、この値を変更しない限り、一見無作為な並び替えに見えますが毎回必ず同じ順序の繰り返しが行われます。この整数のことを乱数のシードと呼びます。シードを実験者が自分で指定してその記録をとっておけば、以前行った実験と全く同一の繰り返し順序を再開できます。研究の目的によってはこのような再現性が必要になるかも知れませんので、各自の判断で選択してください。なお、乱数のシードについてもう少し詳しく知りたい方は「 :numref:`{number}:{name} ` 」をご覧ください。 **[繰り返し条件]** には、条件ファイル名を入力します。 :numref:`fig-conditions-file-buttons` に示すように入力欄の右側にある2つのボタンがあります。左側のボタンをクリックするとファイル選択ダイアログが開くので、先ほど作成した条件ファイルを選択しましょう。特に難しい操作ではないと思いますが、ひとつだけ注意してほしい事があります。 **[繰り返し条件] を入力する前に少なくとも一度、実験(psyexpファイル)を保存してください** 。Builderはpsyexpファイルが保存された場所を基準に条件ファイルを探しますので、一度もpsyexpファイルが保存されていない状態で条件ファイルを指定してしまうと、入力結果がおかしくなってしまう場合があります。この章を読みながら作業している方はすでにexp03.psyexpという名前で実験を一度保存しているはずですので問題は生じませんが、今後自分で実験を作成する時には気を付けてください。 .. _fig-conditions-file-buttons: .. figure:: fig03/conditions-file-buttons.png :width: 80% **[繰り返し条件]** の入力欄の右側のボタン。ファイルを設定済みの状態で右端のボタンをクリックするとExcelなどxlsx編集アプリケーションが起動して条件ファイルの内容を確認、修正できます。 **[繰り返し条件]** に条件ファイルを設定済みの状態で :numref:`fig-conditions-file-buttons` の右側のボタンをクリックすると、Excelなどのアプリケーションで条件ファイルを開いてくれます。条件ファイルの詳細を確認したい時や、内容を修正したい場合に便利なので覚えておいてください。 **[繰り返し条件]** が空欄の時にこのボタンをクリックすると、内容が空っぽのxlsxファイルが作成されます。内容を入力して保存しても自動的に **[繰り返し条件]** に設定してくれないので、手作業で設定する必要があります。ご注意ください。 あと **[試行を繰り返す]** というチェックボックスと **[使用する行 $]** という項目がありますが、 **[試行を繰り返す]** については次章で解説します。 **[使用する行 $]** については「 :numref:`{number}:{name} ` 」をご覧ください。 さて、解説はこのくらいにして実験の作成を進めましょう。今回の実験では **[Loopの種類]** にfullRandomを用いることにして、 **[繰り返し回数 $]** には25を入力しましょう。 **[乱数のシード $]** は空白で良いでしょう。条件ファイルに4つの条件が定義されているので、それぞれを25回ずつ繰り返すと25×4=100試行となり、最初の計画と一致します。そして **[繰り返し条件]** の項目の右端の「選択…」ボタンを押して条件ファイル(exp03_cnd.xlsx)を選択してください。正常に読み込むことができれば、 :numref:`fig-confirm-loop-conditions` 左のように **[繰り返し条件]** の上に条件ファイルの概要が表示されます。 :numref:`fig-confirm-loop-conditions` では「2パラメータ, 4条件」と書かれていますが、「4条件」が条件ファイルの行数(先頭行を除く)、「2パラメータ」が列数に対応しています。次の行に[stim_color, stim_xpos]と書かれているのは条件ファイル先頭行に入力したパラメータ名です。パラメータ名の順番はBuilderが扱いやすいように自動的に並べ替えるので、パラメータ名に過不足がないことだけを確認してください。exp03_cnd.xlsxで定義したパラメータ名と一致していることが確認できたら、ダイアログのOKをクリックしてダイアログを閉じましょう。すると :numref:`fig-confirm-loop-conditions` 右のようにフローペインにループ(左側へ戻る矢印)が表示されます。ループの矢印上にtrialsと書かれた白い四角が表示されていますが、これはループのプロパティ設定ダイアログの **[名前]** で設定したループの名前を示しています。 .. _fig-confirm-loop-conditions: .. figure:: fig03/confirm-loop-conditions.png :width: 90% **[繰り返し条件]** に条件ファイルを指定すると、条件ファイルの概要が表示されます。概要が表示されない場合は条件ファイルの読み込みに失敗していますので条件ファイルの内容を確認しましょう。 一度設定したループを再設定したい場合は、ループの名前が書かれた白い四角にマウスカーソルを重ねて左ボタンをダブルクリックしてください。削除したい場合は、同じくマウスカーソルを重ねた状態で右クリックをしてください。「削除」という項目だけがあるメニューが表示されるので、「削除」を選択しましょう( :numref:`fig-remove-loop` )。 .. _fig-remove-loop: .. figure:: fig03/remove-loop.png :width: 60% ループの再設定と削除 さて、これでいよいよ赤や緑の刺激が左右に表示されるようになりました、と言いたいところですが、まだもう一つ作業が残っています。この節の作業によって、Builderは条件ファイルから条件を読み取って、パラメータを変化させながらルーチンを繰り返し実行できるようになりました。しかし、肝心のルーチンが条件ファイルから読み取られたパラメータを利用できるようになっていません。次の節では、読み取ったパラメータを利用する方法を解説します。 チェックリスト - フローペインでループの挿入を開始できる。 - ループを挿入する際、フローペインの矢印上に表示される黒い円の意味を説明できる。 - ループのプロパティ設定ダイアログで条件ファイルを指定し、表示された条件ファイルの概要が適切か確認できる。 - **[Loopの種類]** のsequential、random、fullRandomの違いを説明できる。 - **[繰り返し回数 $]** の値、条件ファイルに含まれる条件数、ルーチンが繰り返される回数の関係を説明できる。 - **[乱数のシード $]** に値を設定するとどのような効果が得られるか説明できる。 - 条件ファイルを **[繰り返し条件]** に指定する前にpsyexpファイルを保存すべき理由を説明できる。 .. _section-modify-stimuli-using-conditionsfile: パラメータを利用して刺激を変化させよう ---------------------------------------------------- 手始めに、条件ファイルから読み取ったパラメータを使って刺激の位置を左右に変化させてみましょう。ルーチンペインに戻って、stimulusのプロパティ設定ダイアログを開いてください。 **[位置 [x, y] $]** の欄には(0.7, 0)と入力されているはずですが、これを[stim_xpos, 0]に書き換えてください。そして、入力欄の右側にある「更新しない」と書かれたプルダウンメニューをクリックして「繰り返し毎に更新」を選択しましょう( :numref:`fig-set-every-repeat` )。 .. _fig-set-every-repeat: .. figure:: fig03/set-every-repeat.png :width: 60% 条件ファイルからパラメータを読み込んで自動的にプロパティを更新するように設定します。 このようにプロパティ設定ダイアログの項目に、条件ファイル先頭行のパラメータ名を書くと、Builderが実験を実行する時にパラメータの値を自動的に更新してくれます。右側のメニューを「繰り返し毎に更新」にし忘れるという失敗は、ある程度慣れてきたユーザーでも時々うっかりしてしまいがちなので、疑わしい時には警告を表示してくれる機能がBuilderには備わっています。 :numref:`fig-set-every-repeat-warning` のように入力内容が赤色で表示され、ダイアログの下部に「更新されるように設定すべき変数を含んでいるようです」と表示されている場合は、入力内容が間違っていないか、「更新しない」から変更する必要がないかよく確認しましょう。 .. _fig-set-every-repeat-warning: .. figure:: fig03/set-every-repeat-warning.png :width: 60% 「繰り返し毎に更新」を選択し忘れると警告が表示されます。 Builderの警告機能は万全ではありませんので、「繰り返し毎に更新」に設定すべきところを忘れたまま実験を実行してしまうことも起こり得ます。そのようなときは、実験が突然終了してRunnerの画面に戻ってしまいます。この時、Runnerの「標準出力」の欄を見ると、 :numref:`fig-error-variable-not-defined` のように「stim_xposなんて値は知らないよ」というメッセージが表示されているはずです。「繰り返し毎に更新」に設定していないとBuilderが条件ファイルから読み込んだ値をstim_xposに代入するという作業が行われないので、stim_xposという名前の変数が存在していないというのがこのメッセージの意味なのですが、かなり分かりにくいですね。Builderがもう少しわかりやすいメッセージを出してくれたらと思うのですが、技術的にとても難しいことなので人間ががんばって解釈してあげる必要があります。 .. _fig-error-variable-not-defined: .. figure:: fig03/error-variable-not-defined.png :width: 70% 条件ファイルからパラメータを読み込むつもりなのに「更新しない」のまま実行してしまった時に表示されるエラー。 変更作業が終わったら、実験を実行して刺激の位置が左右に変化することを確認してください。これでようやく実験らしくなってきました。そして、エラーで実験が止まることを体験しておくために、ぜひ一度「更新しない」に戻して実行してみてください(体験した後はまた「繰り返し毎に更新」に戻すことを忘れずに!)。 続いて刺激の色も条件に応じて更新するようにしましょう。基本的には位置の更新と同じなのですが、ここにも一つ注意しないといけない点があります。今まで敢えて説明していなかったのですが、プロパティ設定ダイアログの項目には$が最後についているものとついていないものがあることに皆さんは気付いておられるでしょうか。例えば **[位置 [x, y] $]** や **[回転角度 $]** には$が付いていますし、 **[塗りつぶしの色]** や **[文字列]** には$が付いていません。この$記号は、難しい言い方をしますと「入力した値が文字列として評価されるか($なし)、Pythonの式として評価されるか($あり)」を表しています。 具体的な例を挙げましょう。Textコンポーネントの **[文字列]** に Targetと入力されているとします。これは画面上にTargetという文字列を表示したいということでしょうか。それとも、条件ファイルにTargetという名前のパラメータが定義されていて、そのパラメータの値を代入したいということでしょうか。条件ファイルという便利なものを導入した代償に、「各コンポーネントのプロパティに文字列が入力されている場合、それはデータとしての文字列なのか、パラメータの名前なのか」を区別する方法を考えなければいけなくなってしまいました。ここで登場するのが$です。Builderでは、プロパティに入力された値に$が含まれていなければ、その値は文字列であるとみなされます( :numref:`fig-variable-name-or-string` )。従って、先ほど挙げた「 **[文字列]** にTargetと入力されている」例ではTargetという文字列をスクリーン上に提示したいのだと解釈されます。もし$Targetと書かれていれば、Targetという名前のパラメータの値を条件ファイルから読み込むのだと解釈されます。当然、条件ファイル内でTargetという名前のパラメータが定義されていなければエラーになります。 .. _fig-variable-name-or-string: .. figure:: fig03/variable-name-or-string.png :width: 80% $を付けることによって入力した値が名前を表しているのか文字列を表しているのかを区別します。 ここで、読者の皆さんの中には「ちょっと待てよ、じゃあ :numref:`fig-set-every-repeat` の時はなんで$[stim_xpos, 0]じゃなくて[stim_xpos, 0]でパラメータの値を読み込めたの?」と疑問を持った方もいるかも知れません。確かに :numref:`fig-variable-name-or-string` の規則に従うのであれば、 :numref:`fig-set-every-repeat` は$[stim_xpos, 0]と書かないといけないはずです。ここで注目してほしいのが **[位置 [x, y] $]** というプロパティ名の最後の$記号です。この$は本来入力欄に書くべきだった$がプロパティ名に引っ越してきたと思えばよいでしょう。考えてみれば、 **[位置 [x, y] $]** や **[回転角度 $]** と言ったプロパティには文字列が指定される可能性はありません。例えば論文の手続きに「刺激をX度回転した」と書いてあったら、常識で考えてXは変数であって文中のどこかで「Xは30または60」とかいう具合に数値が指定されているはずでしょう。それと同じことで、位置や回転角度のように数値を指定すべきプロパティに文字列が書いてあったら、常識的に考えてそれは名前であるはずです。だから、最初からプロパティ名に$を含ませてしまって、いちいち$を入力しなくてよいようになっているのです( :numref:`fig-expression-mark` )。 .. _fig-expression-mark: .. figure:: fig03/expression-mark.png :width: 80% プロパティ名に$が付いているものは、文字列が指定されることがあり得ないプロパティなので、$を入力しなくても名前として解釈されます。 以上の解説が済んだところで、ようやく条件ファイルを使って刺激の色を変化させる方法を説明することができるようになりました。刺激の色は **[塗りつぶしの色]** と **[枠線の色]** で指定します。これらのプロパティに条件ファイルで定義したパラメータstim_colorの値を代入したいのですが、 **[塗りつぶしの色]** にも **[枠線の色]** にも$はついていません。ではどのように書いたら良いか、もうお分かりですね。正解を :numref:`fig-change-color-every-repeat` に示します。「繰り返し毎に更新」を選択するのを忘れないようにしてください。設定ができたら、実験を実行してみましょう。今度は刺激の位置も色もきちんと条件ファイルに従って変化するはずです。 .. _fig-change-color-every-repeat: .. figure:: fig03/change-color-every-repeat.png :width: 70% 条件ファイルを用いて刺激の色を繰り返し毎に更新する時の設定例。「高度」タブですので注意してください。 これでようやく刺激が完成しました。次は実験記録を保存したファイルを確認しますが、その前に色の指定に関してここまで説明を後回しにしていた問題を取り上げましょう。まず、:numref:`第%s章 ` で色の指定方法について学んだ時に、色空間内の座標による指定では$[1.0, 0.0, 0.75]のように$を必ず付けていました。この節の内容を理解した方は、なぜ$が必要であったか想像がついているのではないかと思います。 **[塗りつぶしの色]** 、 **[枠線の色]** 、 **[色]** にはいずれも$が付いていないので、$なしで[1.0, 0.0, 0.75]と書かれているとBuilderには「[1.0, 0.0, 0.75]という名前の色」に見えてしまうのです。当然こんなヘンテコな名前はweb/X11 Color nameにはありませんので、Builderは「こんな名前の色は知らない」というエラーを出して止まってしまいます。一方、本章で条件ファイルの作成方法を解説した際に「条件ファイル内において色空間座標値で色を指定する場合は$なしで書かねばならない」と述べましたが、こちらはちょっと事情が複雑です。ごく簡単に説明しますと、Builderは条件ファイルから読み込んだ値に関しては「名前ではありえない」と考えます。ですから、条件ファイル内に書かれた$記号は「名前か、文字列か?」を判断するための記号としてではなく、単なる文字として解釈されます。ですから、条件ファイル内に$付きで$[1.0, 0.0, 0.75]と書かれていると、余計な$が付いていることになって色座標値として解釈されなくなってしまうのです。まあ、この辺りはよくわからなければとりあえず置いておいて、「条件ファイル関連でうまく値が読み込まれない時は$記号に問題があるかも知れない」と疑うことを覚えておいていただければ十分かもしれません。では$記号そのものを文字列として表示させたい場合はどうしたらいいの?という点については「 :numref:`{number}:{name} ` 」に書いておきましたので、興味がある方はご覧ください。 チェックリスト - 条件ファイルで定義したパラメータを用いてコンポーネントのプロパティ値を更新できるように設定できる。 - コンポーネントのプロパティ名の最後に$が付いているものと付いてないものの違いを説明できる。 実験記録ファイルの内容を確認しよう ---------------------------------------------- 製作中の実験もかなり体裁が整ってきたので、ここで一度実験記録ファイルの内容について解説しておきましょう。以下の手順 ( :numref:`fig-output-all-datafiles` )で設定を変更してから実験を実行してください。ちょっと面倒ですが、100試行すべて行ってください。 - dataフォルダ内に作成されているファイルをすべて削除する。 - 実験設定ダイアログを開いて、hdf5形式以外のすべての実験記録ファイルを出力するように設定する。すなわち、「xlsx形式のデータを保存」、「CSV形式のデータを保存(summaries)」、「CSV形式のデータを保存(trial-by-trial)」にチェックを付ける(「pydat形式のデータを保存」のチェックはチェックが付いている状態から変更できない)。 - 実験を実行し、実験情報ダイアログのparticipantにfooと入力して実行する。 .. _fig-output-all-datafiles: .. figure:: fig03/output-all-datafiles.png :width: 80% 実験設定ダイアログを開いてすべての記録ファイルを保存するようにチェックして実験を最後まで実行してください。実験開始時の実験情報ダイアログのparticipantにfooと入力してください。 実験が終了したら、dataフォルダの内容を確認してください。 :numref:`tbl-builder-generated-files` に示したファイルができているはずです。ファイル名の先頭部分にはparticipantに入力した文字列が代入されており、続いて実験を実行した時刻が続きます。participantに入力する文字列を工夫すると、データの整理が非常に楽になります。participantを空白のまま実験を実行すると、アンダースコア( \_ )の後に実行時刻が続くファイル名になります。participantにファイル名として使用できない文字列を指定しないように注意してください。 .. tabularcolumns:: |p{16zw}|p{26zw}| .. list-table:: Builderが作成する実験記録ファイル(fooは実験情報ダイアログのparticipantに入力した文字列、yyyy_mm_dd_hhMMは年(西暦)、月、日、時、分) :widths: 36, 64 :header-rows: 1 :name: tbl-builder-generated-files - - ファイル名 - 概要 - - foo_yyyy_mn_dd_hhMM.xlsx - 条件毎に結果をまとめたExcelファイルを保存する。実験設定ダイアログの「xlsx形式のデータを保存」をチェックすると作成される。 - - foo_yyyy_mn_dd_hhMMtrials.csv - 条件毎に結果をまとめたCSVファイルを保存する。実験設定ダイアログの「CSV形式のデータを保存(summaries)」をチェックすると作成される。 - - foo_yyyy_mn_dd_hhMM.csv - 試行毎に結果をまとめたCSVファイルを保存する。実験設定ダイアログの「CSV形式のデータを保存(trial-by-trial)」をチェックすると作成される。 - - foo_yyyy_mn_dd_hhMM.psydat - PythonのcPickleというモジュールを用いて出力された実験記録。自分で分析用Pythonスクリプトを書く場合に用いる。実験設定ダイアログの「pydat形式のデータを保存」をチェックすると作成される。 - - foo_yyyy_mn_dd_hhMM.log - 実験中のPsychoPyの動作記録が保存されている。実験設定ダイアログの「ログレベル $」の選択肢によって内容が変化する。PsychoPy自体の動作解析や開発などに用いる。通常のデータ分析向きではない。実験設定ダイアログの「ログの保存」をチェックすると作成される。 作成されるファイルのうち、拡張子が.logと.psydatのファイルはとりあえず無視してよいでしょう。.psydatファイルは「データ分析は自作のPythonスクリプトをでする」という人しか使わないでしょうし、.logファイルは通常のデータ分析では必要のないファイルです。ただ、「実験が正常に動作していたのか?」という事が問題になった時には.logファイルがあると役に立ちますので、学会や論文で公表する可能性がある実験の.logファイルは保存しておいた方がよいでしょう。 データ分析の際に基本となるファイルは、foo_yyyy_mn_dd_hhMM.csvです。拡張子の.csvは、このファイルの保存形式がカンマ区切りのテキストファイル(comma-separated values; CSV)であることを意味しています。ExcelもLibreOffice CalcもCSVファイルを開くことができますので、以下の解説ではこれらのアプリケーションでCSVファイルを開くという前提で進めます。 foo_yyyy_mn_dd_hhMM.csvをExcelで開くと(LibreOffice Calcでも同様、以下省略)、シートの1行が1回の試行に対応する形で実験記録が保存されていることを確認できます。このファイルは、実験設定ダイアログで「CSV形式のデータを保存(trial-by-trial)」をチェックしていると作成されるので、以下trial-by-trial記録ファイルと呼ぶことにします。1行目は各列の見出しで、2行目が第1試行、3行目が第2試行という具合に101行目(第100試行)までデータがあることを確認してください。列数は条件ファイル数に含まれるパラメータ数やルーチンに配置されたコンポーネントによって変化しますが、一般的に以下の内容が含まれます( :numref:`fig-data-trial-by-trial` )。 .. _fig-data-trial-by-trial: .. figure:: fig03/data-trial-by-trial.png :width: 90% trial-by-trial記録ファイルの内容。「各試行で用いられたパラメータ」は条件ファイルを使用した場合のみ、「Keyboardコンポーネントの出力」はKeyboradコンポーネントを使用した場合のみ出力されます。 各試行で用いられたパラメータ 条件ファイル内で定義されているパラメータの内、どの値が使用されたかが示されています。この情報を含む列の数は条件ファイルの列数に対応しています。実行した実験で条件ファイルが使用されていない場合は出力されません。 繰り返しに関する情報 その行の試行が何回目の繰り返しの何試行目にあたるか、全体を通して数えて何試行目にあたるかといった情報が示されています。 :numref:`fig-data-trial-by-trial` のtrials.thisRepNは何回目の繰り返しか、trials.thisTrialNはその繰り返しにおける何試行目か、trials.thisNは全体を通して何試行目か、trials.thisIndexはその試行で用いられたパラメータが条件ファイルの何個目の条件に相当するかを示しています。Pythonでは「順番は0番目から数える」という規則がありますので、第1試行が0と表記されていることに注意してください。また、列見出しのtrialsの部分はBuilderにおけるループの名前に対応しています。 刺激の開始・終了に関する情報 各試行で刺激が(描画)開始・終了された時刻が、実験開始を0秒として秒単位で出力されています。何か実験中に異常があって描画タイミングがおかしくなったりしていなかったかをこれらの値で確認することができます。終了時刻が設定されていない刺激では終了時刻がNoneとなります。この情報が不要な場合は「 :numref:`{number}:{name} ` 」を参照してください。 キー押しに関する情報 実験にKeyboardコンポーネントが含まれていなければ出力されません。key_resp_2.keysは押されたキーのキー名、key_resp_2.rtはKeyboardコンポーネントが有効になってからキーが押されるまでの時間を示しています。単位は秒です。列見出しのkey_resp_2の部分はBuilderにおけるKeyboardコンポーネントの名前に対応しています。なお、時間が小数点以下ものすごい桁数まで出力されていますが、計測に詳しい方は「一体この値はどの程度精度があるのか」と不安になるかもしれません。PsychoPy Builderが出力する時間の精度については「 :numref:`{number}:{name} ` 」をご覧ください。 キー押し検出開始・終了に関する情報 実験にKeyboardコンポーネントが含まれていなければ出力されません。Keyboardコンポーネントがキー押し検出を開始・終了した時刻が、実験開始を0秒として秒単位で出力されています。終了時刻が設定されていない場合は終了時刻がNoneとなります。その他の実験に関する情報 実験実施日や実験名、実験情報ダイアログで入力した値、使用したPsychoPyのバージョン、フレームレートなどが示されています。フレームレートとは、1秒あたりに描画したフレーム数のことで、モニターのリフレッシュレートと大きく異なる場合はスクリーンの描画に問題が生じている可能性があります。リフレッシュレートとフレームについては「 :numref:`{number}:{name} ` 」をご覧ください。特にこの値がモニターのリフレッシュレートより大幅に小さい場合は、スクリーンの描画に遅延が生じていて刺激が適切な時刻に表示されていない恐れがあります。 今回の実験では、刺激が提示される位置と反応する指の関係が反応の速さや正確さにどのように影響するかを調べるのが目的ですから、刺激の位置と色の組み合わせ別に、正答率と反応時間を計算すればよいでしょう。すでに自分自身でいろいろなアプリケーションを用いて実験を行っている方は各自で好みの方法で分析していただければよいですが、こういった分析が初めての方はとりあえずstim_colorとstim_xposでデータを並べ替えしてみましょう。するとそれぞれの条件に対応する試行が集まりますので、ワークシート関数を用いて平均値を求めたり、条件毎にxキーとslashキーが押された回数を数えれば計算することができますが、平均値の計算と比べれば手間がかかります。実は、Builderには参加者が押したキーが正答であったか否かを判定して記録する機能があり、これを使うと正答率の計算は楽になります。次節ではこの方法を学びます。 続いて「xlsx形式のデータを保存」をチェックすることで出力される拡張子がxlsxのファイルと、「CSV形式のデータを保存(summaries)」をチェックすることで出力される拡張子がcsvのファイルについても確認しておきましょう。これらはいずれも条件ファイルで定義された実験条件ごとに結果を1行に要約したもので、内容はほぼ同じです。拡張子がxlsxのファイルを開いてみてください。 :numref:`fig-data-xlsx` のような内容になっているはずです。 .. _fig-data-xlsx: .. figure:: fig03/data-xlsx-with-datatab.png :width: 90% xlsx記録ファイルの内容。データが1条件1行でまとめられています。 ひとつの実験条件が1行にまとめられるため、本章の例では4行となります。条件ファイルの行数と同じですね。各行の最初に条件ファイルに記述されているパラメータが示されています。パラメータの次にはnという見出しの列があり、各条件に対応する試行が何試行あったかが記されています。 :numref:`fig-data-xlsx` ではすべて25となっています。一般に、nの値はループの **[繰り返し回数 $]** に一致します。さらに続いて、各条件のデータが数十列にわたって出力されています。これらの行の下には、実験の実施時刻やフレームレート、実験情報ダイアログの内容といった実験に関する情報が記されています。この記録形式は **[繰り返し回数 $]** が増えると非常に列数が多くなるという問題があるのですが、条件毎の正答率や平均反応時間といった情報が出力されるので、trial-by-trial記録ファイルから自分で計算する手間が省けるという利点があります。章末の「 :numref:`{number}:{name} ` 」に詳しく解説しておきますので、興味がある方はそちらをご覧ください。どちらを使うかは好みの問題ですが、本書ではtrial-by-trial記録ファイルを使用します。 チェックリスト - expInfoのparticipantに設定した文字列が記録ファイル名にどのように反映されるかを説明できる。 - dataフォルダに作成される拡張子logとpsydatのファイルに何が記録されているか、概要を説明することができる。 - CSVファイルのCSVとは何の略であり、何を意味しているか説明することができる。 - trial-by-trial記録ファイルから、各試行で用いられたパラメータの値を読み取ることができる。 - trial-by-trial記録ファイルから、各試行において押されたキーのキー名と反応時間を読み取ることができる。 - trial-by-trial記録ファイルに記録されている反応時間の計測開始時点(0.0秒になる時点)がどのように決まるか答えることができる。 - trial-by-trial記録ファイルから実験情報ダイアログで入力した値を読み取ることができる。 - trial-by-trial記録ファイルから実験実行時のフレームレートを読み取ることができる。 - 分析時に未変更の記録ファイルを保存しておいた方がよい理由を説明できる。 反応の正誤を記録しよう -------------------------------------- Builderの画面に戻って、exp03.psyexpを開いてください。そしてKeyboardコンポーネントのプロパティ設定ダイアログを開きましょう。 :numref:`fig-set-correct-ans` に示す通り **[正答を記録]** という項目がありますが、この項目をチェックすると **[正答]** という項目に入力できるようになります。ここに正答となるキー名を入力しておくと、Builderが押されたキーが正答キーと一致するか否かを判定して記録ファイルに保存してくれます。xキーが正解ならば'x'、 / キーが正解であれば'slash'です。GO/NOGO課題のように「押さないのが正解」の場合はNoneと入力します。Noneの前後にクォーテーションマークが付いていないことに気を付けてください。 多くの心理学実験では、条件によって正答となる反応が変化します。従って、 **[正答]** に入力するキー名は条件毎に変化させる必要があります。「条件毎に変化する」となると、条件ファイルの出番です。刺激が赤色の時にxキー、緑色の時に / キーを押すのが正答ですが、この関係は作成済みの条件ファイルに含まれている値からはわからないので、正答のキー名を示すパラメータ列を条件ファイルに追加する必要があります。刺激の位置と色を変化させた時にはまず条件ファイルの作成から始めましたが、どのようなパラメータ名を使用するかすでに決めているのであれば、Builder側の作業から始めてしまっても問題はありません。correct_ansという列を条件ファイルに追加して、そこへ正答キー名を入力することにしましょう。 .. _fig-set-correct-ans: .. figure:: fig03/set-correct-ans.png :width: 70% 反応の正誤を記録するよう設定する手順。 Keyboardコンポーネントのプロパティ設定ダイアログの **[正答]** に「correct_ansから値を代入して繰り返し毎に更新する」ように設定しないといけないのですが、ここで条件ファイルの参照について皆さんがきちんと理解しているかテストです。 **[正答]** に入力する値はcorrect_ansですか、それとも$correct_ansですか? 答えは$付きの$correct_ansです。なぜ$が必要かをきちんと説明できない方は、もう一度$記号について復習しておきましょう。繰り返し毎の更新でもう一つ注意すべき点として「「繰り返し毎に更新」を忘れずに選択する」というものがありましたが、 **[正答]** の右側にはそもそもプルダウンメニューがありません。この項目に関しては、「繰り返し毎に更新」を選ばなくても更新が行われます。 **[正答]** の設定が終わったら、今度はExcelを開いて条件ファイルを編集しましょう。correct_ansと1行目に書かれた列を追加して、正答キー名を入力してください。正答キーは刺激の色と対応しているのですから、stim_colorがredの行はx、greenの行はslashが正答キーです( :numref:`fig-edit-correct-ans` )。入力したら条件ファイルを保存しましょう。条件ファイルの名前や保存場所を変更していなければ、Builderで条件ファイル名を設定し直す必要はありません。試しにBuilderに戻ってフローペインのループを左クリックしてループのプロパティ設定ダイアログを表示させると、相変わらずパラメータはstim_colorとstim_xposの二つと表示されています。しかし、実行するときちんと新しく追加したパラメータも読み込まれません。正しく表示されないと気持ち悪いという方は、もう一度条件ファイルを設定し直してください。正しくstim_color、stim_xposとcorrect_ansの3パラメータが表示されるはずです。 .. _fig-edit-correct-ans: .. figure:: fig03/edit-correct-ans.png :width: 50% 条件ファイルにcorrect_ansの列を追加し、正答キー名を入力します。 Keyboardコンポーネントと条件ファイルの修正が終わったら、実験を実行してみましょう。きちんと100試行終わるまで実行してください。終了したら、trial-by-trial記録ファイルの内容を確認してみましょう( :numref:`fig-check-correct-ans` )。trial-by-trial記録ファイルにはkey_resp_2.corrという列が追加されています。この列の値が1の試行は正答で、0の試行は誤答です。ということは、その平均値を計算すれば正答率(0.0=全問不正解、1.0=全問正解)を計算できるというわけです。 .. _fig-check-correct-ans: .. figure:: fig03/check-correct-ans.png :width: 80% **[正答]** を設定すると記録ファイルに正答/誤答が記録されます。 以上で、サイモン効果を題材としたこの章の実験は「一応」完成しました。「一応」というのは、確かに最初に計画した目標は一通り達成しているのですが、実際にこのpsyexpファイルを使って参加者を募って実験するとなるといくつか不都合な点があるからです。例えば、実験を実行して実験情報ダイアログに値を入力すると、直ちに最初の試行が始まってしまいます。実験者が実験情報ダイアログに入力する場合、入力したらすぐに実験参加者にキーボードを渡さないと最初の試行の刺激に反応できないでしょう。また、実験参加者に対する教示も実験開始前にスクリーン上に表示しておきたいものです。終了時もいきなりBuilderのウィンドウに戻るのではなく、何か一言実験参加者へのお礼や指示があると気が利いていて良いでしょう。次の節では、こういった気配りを実験に組み込む方法を解説します。 チェックリスト - 正答/誤答を記録するようにKeyboardコンポーネントを設定することができる。 - キーを押さないことが正答となるように設定することができる。 - 正答となるキー名を条件ファイルから読み込んで繰り返し毎に更新することができる。 - trial-by-trial記録ファイルから、各試行の正答/誤答を読み取ることができる。 ルーチンを追加して教示などを表示しよう ------------------------------------------- この節では、exp03.psyexpの実験開始時と終了時に教示などを表示させます。一口で教示を表示すると言っても「イラストで教示するのか、文章で表示するのかなど」いろいろと選択肢がありますが、ここでは文章で表示することにしましょう。 文章を表示するとなるとTextコンポーネントの出番ですが、ここまで解説してきた方法だけではうまく表示することができません。というのも、今まで通りルーチンペイン上にTextコンポーネントを配置してしまうと、繰り返しの度に表示されてしまうので「実験開始時と終了時」ではなくて試行毎の表示になってしまうのです。繰り返しが始まる前や後に何かを表示したいときには、新しいルーチンを追加する必要があります。 :numref:`fig-insert-new-routine` はフローペインを使って新しいルーチンを作成してフローに挿入する手順を示しています。まず、フローペイン左端のInsert Routineをクリックします。すると(new)とtrialという二つの項目があるポップアップメニューが表示されます。「繰り返しを設定しよう」の節で少しだけ触れましたが、PsychoPyで実験を新規作成した時に最初から表示されているルーチンはtrialという名前がついています。ポップアップメニューのtrialという項目を選択すると、trialルーチンがもう一つフローに挿入されます。同じルーチンを何個も挿入してどうするのかと思われるかもしれませんが、その例は練習問題で触れることにしましょう。 新しくルーチンを作成してフローに挿入する場合は、(new)を選択します。すると挿入するルーチン名を入力するダイアログが表示されますので、わかりやすい名前を決めて入力しましょう。名前はパラメータ名に使用できる文字列と同様の規則を満たすものでなければいけません。また、すでにパラメータ名やコンポーネントの **[名前]** プロパティで使用している名前とも重複してはいけません。ここでは実験開始前に教示を表示するためのルーチンということでinstructionという名前を付けておきます。なお、PsychoPy 2022.1からはルーチンの名前を決めるダイアログに「テンプレート」という機能が追加されています。これについては「 :numref:`{number}:{name} ` 」をご覧ください。 .. _fig-insert-new-routine: .. figure:: fig03/insert-new-routine.png :width: 90% フローペインから新しいルーチンの追加を追加します。 名前を決定すると、新しいルーチンをフローのどの位置に挿入するかを指定しなければいけません。フロー上でマウスカーソルを動かすと、マウスカーソルが挿入可能な位置に重なった時に黒い丸が表示されますので、ループの前を選んで挿入してください。すると :numref:`fig-insert-new-routine` の右上のようにinstructionと書かれた四角いアイコンがループの前に挿入されます。同時に、ルーチンペインの左上にinstructionと書かれたタブが出現しているはずです。フローのinstructionと書かれたアイコンか、ルーチンペイン左上のinstructionと書かれたタブをクリックすれば、まだコンポーネントが配置されていない空白のルーチンが表示されるはずです。この空白のルーチンが新たに挿入されたinstructionルーチンです。 instructionルーチンの編集を始める前に、操作方法の確認を兼ねてもうひとつ実験終了時のメッセージを表示するためのルーチンを追加しておきましょう。ルーチン名はthanksとします。ここでは三つの点を確認しておいてください( :numref:`fig-edit-flow` )。 - フローペインの左端のInsert Routineを使ってフローにルーチンを挿入する時にポップアップメニューにinstructionルーチンが含まれていること。 - フロー上の挿入済みルーチンの上にマウスカーソルを重ねて右クリックするとポップアップメニューが表示され、とルーチンをフローから削除したり名前を変更したりできること。 - 上記の方法でフローからルーチンを削除しても、該当するルーチンはルーチンペインに残ったままであること。 .. _fig-edit-flow: .. figure:: fig03/edit-flow.png :width: 60% フローペインにおけるさまざまな操作。フローからルーチンを削除してもルーチンそのものは削除されません。 特に、フローからルーチンを削除してもルーチンそのものはルーチンペインに残っているという点は覚えておいてください。バージョン2020.2.6現在でBuilderはフローにおけるルーチンの並び替えをサポートしていませんので、ルーチンの順番を変えたいときには一旦ルーチンをフローから削除して再挿入する必要があります。その際、一旦フロー上から目的のルーチンがなくなってしまっても全く問題ありません。 さて、instructionとthanksのルーチンを追加してそれぞれループの前と後ろに挿入ら、ルーチンの編集に入りましょう。まずinstructionルーチンでは、画面中央に以下のような教示を画面上に提示することにしましょう。 :: 画面の中央に白い十字が表示されたあと、すこし遅れて赤色または緑色の円が表示されます。 刺激の色を見て、以下のキーをできるだけ速く間違わずに押してください。 赤色:左手人差し指でキーボードのxキー 緑色:右手人差し指でスラッシュ( / )キー スラッシュキーを押すと課題が始まります。 100問終了するまで休憩できないので注意してください。 実験参加者の中には「スラッシュキー」と言われてもどのキーかわからない方もいるでしょうから、キーの確認も兼ねてスラッシュキーを押して実験を開始することにしてみましたが、スペースキーなどの実際の反応で使用しないキーを割り当てるのもよいでしょう。上記の文章を表示するためのTextコンポーネントの設定については、ここまで作業してきた皆さんでしたらヒントなしでできると期待します。 ひとつ注意すべき点は、ルーチン終了時刻の指定です。教示に「スラッシュキーを押すと課題が始まります。」と書いてあるのですから、Keyboardコンポーネントを使用して、スラッシュキーが押されたらルーチンを終了するように設定すればよいでしょう。もちろんTextコンポーネントとKeyboardコンポーネントの **[終了]** は空白にしておきます。ここまではすでに解説済みのテクニックですが、このままだと記録ファイルに「課題を開始する時に押したスラッシュキー」まで保存されてしまいます(ただし :numref:`第%s章 ` 参照)。分析に必要な反応が記録されなくなってしまうわけではないので致命的な問題ではありませんが、分析と無関係なキー押しが記録されていると分析の際に思わぬ手間がかかる恐れがあります。 キー押しを記録したくない場合には、Keyboardコンポーネントのプロパティ設定ダイアログを開いて、 **[記録]** を「なし」に設定しましょう( :numref:`fig-dont-record-keys` )。そのKeyboardコンポーネントで検出されたキー押しは一切記録されません。「そのKeyboardコンポーネントで」と断ったとおり、ひとつの実験に複数のKeyboardコンポーネントを配置している場合、個々のKeyboardコンポーネントで独立に **[記録]** の設定を行うことができます。今回の実験の場合、instructionルーチンに配置するKeyboardコンポーネント **[記録]** を「なし」にして、trialルーチンに配置するKeyboardコンポーネントは「最後のキー」のままにしておけばよいでしょう。これでinstructionルーチンは完成です。 .. _fig-dont-record-keys: .. figure:: fig03/dont-record-keys.png :width: 80% Keyboardコンポーネントで **[記録]** を「なし」に設定すると、そのKeyboardコンポーネントで検出したキー押しが記録ファイルに出力されません。 続いてthanksルーチンですが、ここではTextコンポーネントを使用して「終了しました。ご協力ありがとうございました。」というメッセージを3秒間表示することにしましょう。Textコンポーネント以外のコンポーネントを配置する必要はありません。特に難しい点はないはずですが、ひとつ解説しておきたい点があります。Textコンポーネントの **[終了]** の設定を終えた後にフローペインを見ると、thanksルーチンだけ緑色で表示されていて、小さく3.00sと表示されているはずです(表示されていない場合はメニューの「ビュー」から「Flowを大きく」を選択してみてください)。対して、trialやinstructionルーチンは青色で表示されています( :numref:`fig-routine-duration` )。緑色のルーチンは、中に含まれるすべてのコンポーネントの終了時刻が確定していて、ルーチン開始から終了までに要する時間が計算できることを示しています。青いルーチンは、キーが押されるまで終了しないルーチンのように、ルーチン開始から終了までの時間が実行時にならないと確定しないことを示しています。 .. _fig-routine-duration: .. figure:: fig03/routine-duration.png :width: 80% 青いルーチンは終了時刻が確定していないことを、緑色のルーチンは終了時刻が確定していることを表しています。緑色のルーチンにはルーチンの実行時間の見積もりが表示されています。 以上でこの節の目標は達成しましたが、ルーチンの新規作成やフローへの挿入について解説したついでに、Builderウィンドウ上部のメニューの「実験」という項目について補足しておきます(:numref:`fig-copy-paste-routine` 上)。メニューの「実験」からは、ルーチンの新規作成やコピー&ペースト、フローへのルーチンとループの挿入の操作ができます。これらの操作のうち、ルーチンの新規作成とフローへのルーチンとループの挿入はフローペイン左端の「Routineを挿入」や「Loopを挿入」を用いる方法とほぼ同じです。ルーチンのコピー&ペーストは、内容がわずかに異なるルーチンを複数作る必要がある時に便利な機能です。 試しにルーチンペインにtrialルーチンを表示している状態で、「実験」メニューから「Routineのコピー」を選択してください。続いてもう一度「実験」メニューを開いて「Routineの貼り付け」を選択しましょう。すると新しいルーチンの名前を入力するダイアログが表示されるので、他のルーチンやコンポーネントなどと名前が重複しないように新しい名前を入力してください。すると、trialと同じコンポーネントが配置された新しいルーチンが作成されます。ただし、同じコンポーネントが配置されていると言っても、各コンポーネントの名前はBuilderがコピー元のルーチンに含まれるコンポーネントの名前と重複しないように自動的にアンダーバー+数字が付けられるので注意してください (:numref:`fig-copy-paste-routine` 下)。 .. _fig-copy-paste-routine: .. figure:: fig03/copy-paste-routine.png :width: 50% ルーチンのコピー&ペースト。コンポーネントの名前が重複しないように、ペーストされたルーチン内のコンポーネント名には元のコンポーネント名にアンダーバー+数字が自動的につけられます。 ルーチンの新規作成、コピー&ペーストときたら、削除の方法についても知りたいところです。削除はルーチンペイン左上のタブから行います。現在選択中のタブにはルーチン名の右に×マークが表示されています。この×を左クリックすると、そのタブのルーチンが削除されます( :numref:`fig-discard-routine` )。誤って削除してしまった場合はすぐにツールバーの元に戻すボタンをクリックしましょう。 .. _fig-discard-routine: .. figure:: fig03/discard-routine.png :width: 50% ルーチンを削除するにはタブに表示されている×をクリックします。誤って削除してしまったなどの理由で削除を取り消したい場合は元に戻るボタンを使います。 以上で本章の解説を終えたいとと思います。簡単な実験であれば本章の内容だけで十分に実現できるはずです。締めくくりとして、本章で解説したテクニックを応用する練習問題を出しておきます。本章の内容をマスターできたと思った方は是非挑戦してください。 チェックリスト - ルーチンを新たに作成してフローに追加することができる。 - 既存のルーチンをフローに追加することができる。 - フローからルーチンを削除することができる。 - フローペインの赤いルーチンと緑のルーチンが何に対応しているか説明することができる。 - 特定のKeyboardコンポーネントが検出したキー押しを記録しないように設定することができる。 - 既存のルーチンと同一の内容を持つ新しいルーチンをコピー&ペーストの機能を使って作成することができる。 練習問題:練習試行を追加しよう ------------------------------------------------ 先ほどはinstructionルーチンを終えて実験を開始する際に、実験参加者にスラッシュキーを確認させることも兼ねてスラッシュキーでinstructionルーチンを終了するようにしました。しかし、本来であれば本試行と同様の手続きの練習試行を数回体験させてから実験を開始するべきです。練習と本試行を別々のpsyexpファイルとして作成するのも良いのですが、ここでは練習問題ということで単一のpsyexpファイルで練習試行と本試行を実施するように改造してみましょう。 :numref:`fig-practice-add-practice` はこの練習問題で作成する実験の流れです。本試行と終了メッセージは本章で作成した実験から変更する必要はありません。教示はもうひとつルーチンを追加する必要があるでしょう。この練習問題のポイントは、いかに手間をかけずに練習試行を作成するかです。ヒントは「フローの中に同一のルーチンを複数回挿入できる」という点と、「練習試行と本試行はループ回数が違うだけで条件は同じ」という点の二点です。これでもまだピンと来なければ、 :numref:`fig-practice-add-practice` の一番下のフローも参考にしてください。 .. _fig-practice-add-practice: .. figure:: fig03/practice-add-practice.png :width: 80% 練習問題。本試行を開始する前に12試行の練習を行うように改造してみましょう。一番下は作成例のフローを示しています。 この章のトピックス --------------------------------------------------- .. _topic-how-to-confirm-key-name: 自分のキーボードで使えるキー名を確かめる ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Builderを起動し、ルーチンペインにKeyboardコンポーネントとTextコンポーネントを配置して以下のように設定してください。 - Keyboardコンポーネント - **[名前]** をtest_keyboardとする。 - **[終了]** を空白にする。 - **[Routineを終了]** のチェックを外す。 - **[検出するキー $]** を空白にする。 - Textコンポーネント - **[終了]** を空白にする。 - **[文字列]** に$test_keyboard.keysと入力する。$記号やピリオドには重要な意味があるので忘れずにつける。間に空白文字を含んではいけない( :numref:`第%s章 ` 、:numref:`第%s章 ` 参照)。 - **[文字列]** の横にある「更新しない」と書かれたプルダウンメニューを開いて「フレーム毎に更新する」を選択する。 - 一度実行してみて、字が小さすぎたなら **[文字の高さ $]** を調節する。 - 実験設定ダイアログ - Full-screen Windowのチェックを外す。このチェックを外しておかないとESCによる強制終了が効かなかった時に強制終了させるのが面倒なので忘れずにチェックを外しておく。 以上の設定を行ったら実験を保存して実行し、適当にキーボードのキーを押してみてください。押したキーに応じてスクリーン中央に文字列が表示されるはずです。これが押したキーに対応するキー名です。通常はESCキーを押すと強制終了できますが、この実験では画面上に escape とESCキーのキー名が表示されて実験が終了しない場合があります。その場合はあわてずにRunnerのウィンドウを選んで実験中断ボタンを押してください。実験が終了します。 .. _topic-test-reserved-names: Builderで使用できない名前を判別する ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Builderを起動し、適当なコンポーネントをルーチンに配置して、 **[名前]** に名前として使用したい文字列を入力してみましょう。文字列がPythonの予約語やPsychoPyのモジュール名、Builderの予約語に一致する場合は、 :numref:`fig-check-valid-name` のようにプロパティ設定ダイアログの下部に赤色でエラーメッセージが表示されます。ダイアログ左下のOKボタンをクリックできなくなりますので、意図せずに予約語を名前に使用してしまった場合でもまず気づくでしょう。 .. _fig-check-valid-name: .. figure:: fig03/check-valid-name.png :width: 70% Builderで適当なコンポーネントをルーチンに配置して **[名前]** に文字列を入力することによって、その文字列が予約されていないかを確認することができます。 この方法でチェックできるのは予約語などと一致する場合と、自分で定義した他のコンポーネントの **[名前]** や条件ファイルのパラメータ名などと一致している場合です。ただし、 :numref:`第%s章 ` で紹介する、読み込む条件ファイルを実行時に切り替える方法を用いている場合は、Builderは名前の重複を判断できません。実験作成者が管理する必要があります。 .. _topic-random-seed: 無作為化と疑似乱数 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 予測不可能な順序に並べられた数の列のことを乱数(または乱数列)と呼びます。乱数には、一様乱数や正規乱数など、値の出現確率の違いによってさまざまな種類があります。コンピュータゲームなどにおいて人間にとって予測困難な動作を実現する際には、乱数が非常によく用いられます。例えば「地図上を歩き回っていると予測困難なタイミングで敵と遭遇する」というゲームの場合、「地図上を一歩歩くごとに乱数の先頭から順番に値をひとつ取り出し、その値を20で割った余りが0であれば遭遇する」といった処理を行うと上手くいきます。10で割ると遭遇しやすくなり、100で割るとめったに遭遇しないといった具合に遭遇頻度の調節もできます。 このように便利な乱数ですが、実は完全な乱数を発生させるのは難しいことで、代用のために「乱数っぽく見える」数列を作成する方法がいろいろと考案されてきました。「乱数っぽく見えるけれども、実は確定的な計算によって生成されている数列」のことを疑似乱数と呼びます。疑似乱数はシード(seed)と呼ばれるパラメータを持っており、シードの値が一定であれば毎回同じ数列が得られます。あまり良い例ではないかも知れませんが、関数 y=sin kx (kは定数)において、kの値が一定であればx=1,x=2,x=3,…の時のyの値は何度計算しても同じです。しかし、kの値を変えればx=1,x=2,x=3,…の時のyの値は変化します。y=sin kx程度の式であれば生成される数列に規則性があることはすぐにわかりますが、工夫して疑似的に乱数としての性質を持つ数列を生成するように考えられた式が疑似乱数というわけです。 Builderでは、 **[乱数のシード $]** が空白であれば、実験実行時にBuilderが適当なシードを決定して疑似乱数を発生させます。 **[乱数のシード $]** に整数が与えられていれば、それをシードとして疑似乱数を発生させます。そして、生成した疑似乱数を用いて条件の実行順を並び替えます。ですから **[乱数のシード $]** を指定すれば必ず同じ順番で繰り返しが行われるのです。 .. _topic-select-condition-rows: Loopのプロパティ設定ダイアログの **[使用する行 $]** について ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ この機能を使いこなすには :numref:`第%s章 ` 以降で学ぶ知識が必要なので、Pythonの文法をご存じない方はひとまずこの機能は無視して先へ進むことをお勧めします。 **[使用する行 $]** は、条件ファイルで定義されている条件のうち、一部分だけを利用して実行したい場合に利用します。1行に1条件が定義されているので、使用したい条件が書かれている行番号をカンマ区切りなどで列挙します。注意が必要なのは、Pythonは順番を表現するときは最初を「0番目」と書く点です(:numref:`第%s章 `)。 具体的な使用方法ですが、例えば今回の実験で条件ファイルの1行目と3行目に書かれた条件のみを実施する場合には :: "0,2" と書きます。" "を忘れないでください。他にもリストやタプル( :numref:`第%s章 ` 、:numref:`第%s章 `)を用いて :: (0,2) [0,2] という書き方も受け付けます。この場合は" "が不要です。連続する多数の行を指定する場合はスライス(:numref:`第%s章 `)を使用します。 :: [:20] 筆者は普段この機能を利用しないのですが、:numref:`第%s章 ` で学ぶ「実験ダイアログからの情報の取得」を利用して、実行時に利用する行を指定するといった使い方が便利そうです。また、数か月、数年後に実験を再確認する必要が出てきた場合に備えて、条件ファイルにコメントを書いておいて、この機能を用いてコメント行を読み飛ばすといった使い方もできるでしょう。 .. _topic-dollar-character-in-string: $を含む文字列を提示する ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 本文中で、Textコンポーネントの **[文字列]** プロパティに$を入力すると条件ファイル内で定義されたプロパティの値を代入することができると述べました。では、Textコンポーネントで「$を含む文字列を表示させたい」場合はどうすればいいのでしょうか。ただ$を書くとBuilderに「名前」として判断されてしまうため、目的を達成できません。一番シンプルな解決策は、「半角ではなく全角の$を使う」というものです。コンピュータにとって半角と全角の$は全く別の文字なので、問題なく表示することができます。 どうしても半角の$を使いたい、という場合はエスケープ文字を利用する方法があります。エスケープ文字とは半角のバックスラッシュ( :math:`\backslash` )のことで、日本語フォントでは円記号(¥)として表示されます。こう書くと初心者の方は「エスケープ文字って何?」と「日本語フォントでは円記号で表示されるってどういう意味?」という二つの疑問を持たれることと思いますが、まずエスケープ文字の説明から始めましょう。 エスケープ文字の役割は、Builderにおける$の役割と似ています。例えばPythonのスクリプトにおいては、Targetという文字列がデータとして文字列を表すのか、データに対してつけられた名前(変数)を指すのかを区別するために、文字列の前後を半角のシングルクォーテーションまたはダブルクォーテーションで囲みます。 .. csv-table:: 変数と文字列の区別 Target, Targetという変数 \"Target\", Targetという文字列 言語によってダブルクォーテーションのみしか使えないなどの違いがありますが、このような表記は多くのプログラミング言語で用いられています。さて、Pythonの場合、シングルクォーテーションやダブルクォーテーション自体を含む文字列、例えば He said, "Please respond as quickly and precisely as possible." という文字列はどう表記すればよいのでしょうか。何も考えずに前後にダブルクォーテーションを付けてしまうと **"He said, "** Please respond as quickly and precisely as possible. **""** となってしまい、"He said, "までがダブルクォーテーションで囲まれていて、Pleaseからpossibleまでは囲まれてないことになってしまいます。最後に""が残りますが、これは「何も文字がない文字列」と解釈されます。数字の0のようなもので、空文字列と呼ばれます。 この問題の回避方法として、「文字列中に含まれるダブルクォーテーションの前には\\を付ける」という記法が用意されています。これを使うと、先の文字列は "He said, **\\"** Please respond as quickly and precisely as possible. **\\"** " と表記することができます。多くのプログラミング言語において、\\には「その直後に続く文字(列)を通常とは異なる方法で解釈させる」という役割があります。\\などの特別な文字によって、後続の文字を通常とは異なる方法で解釈させることをエスケープと呼び、エスケープによって異なる意味を示す文字列をエスケープシーケンスと呼びます。エスケープシーケンスを開始する記号(ここでは\\)はエスケープシーケンスプレフィックスやエスケープ文字などと呼びます。He said,…の例文では、\\"と書くことによって\\に続く " が「文字列の終了を表す」という通常の意味を失って、単なる " という文字だと解釈されています。もし皆さんが将来プログラミング言語を本格的に学習するのであれば、他にもさまざまなエスケープの例に出会うことになるでしょう。なお、Pythonに限って言えば、文字列をシングルクォーテーションで囲んでも良いことと、シングルクォーテーションで囲まれた文字列の中ではダブルクォーテーションを自由に使うことができるということも付け加えておきたいと思います。 以上を踏まえてBuilderのTextコンポーネントの話に戻りましょう。Textコンポーネントで$を含む文字列を表示したい場合にも、\\によるエスケープが利用できます。つまり、\\$と書けば$を表示することができます。ぜひ試してみてください。なお、本文中で述べた「Builderは条件ファイル内に書かれた$記号を単なる文字として解釈する」というルールはここでも有効ですので、Textコンポーネントの **[文字列]** プロパティの値を条件ファイルから読み込んで表示する場合にはエスケープをする必要はありません。$を含む文字列をそのまま表示することができます。 最後に蛇足ですが、「日本語フォントでは円記号で表示されるってどういう意味?」という疑問にもお答えしておきましょう。コンピュータでは、文字を管理するためにすべての文字に数値を割り当てています。例えばアルファベットの大文字のAは0x41、Bは0x42、小文字のaは0x61が割り当てられています。この数値を文字コードと呼びます。困ったことに、現在のコンピュータでは歴史的な経緯から複数の文字コードが使用されており、ある文字コードで書かれた文書を別の文字コードで解釈すると、本来意図されていた文字とは全く別の文字として解釈されてしまいます。昔の電子メールで時々生じていた「文字化け」の原因のひとつが送信側と受信側で使用している文字コードの違いでした。今回問題になっているバックスラッシュ( :math:`\backslash` )は、初期のコンピュータからずっと利用され続けているASCIIコードという文字コードで0x5Cに割り当てられています。一方、日本のコンピュータで最初に用いられたJIS規格の文字コードでは、大半がASCIIと共通のコードが割り当てられていたのですが0x5Cには円記号(¥)が割り当てられていました。結果として、同じ0x5Cというコードの文字が、解釈に用いるコードによってバックスラッシュになったり円記号になったりするようになってしまったのです。現在のコンピュータでは、欧文フォントを用いて表示するとバックスラッシュで表示され、日本語フォントを用いて表示しなおすと円記号になるといった具合に使用するフォントによって表示が切り替わるという現象が見られます。 .. _topic-clock-resolution: PsychoPyの時間計測の精度について (上級) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 本文中でも述べた通り、PsychoPyの記録ファイルを確認すると、キーが押された時刻が 0.766847908126秒 のように小数点以下かなりの桁数が出力されています。この数値は一体何桁目まで信頼できるのでしょうか。 残念ながらこの疑問の答えはPsychoPyを実行しているハードウェアやOS、デバイスドライバに依存するので一概には答えられません。筆者が主にプログラムの開発等に使用しているPCでは、約2.6MHzのタイマーカウンターが使用されているようです。分解能は約260万分の1秒ですから :math:`3.8 \times 10^{-7}` 、0.38マイクロ秒です。Web上でいろいろな資料を確認する限り、この周波数はあまり高くない部類で、10MHzを超えるタイマーカウンターが利用できる場合もあるようです。反応時間を指標とした心理学実験の論文では「ミリ秒」の小数点1桁まで報告されることがしばしばありますが、その用途には十分な分解能があると言えます。 むしろ注意しないといけないのは、実験参加者がキー押しの動作をはじめてから実際に「キーが押された」とPsychoPyのプログラムまで到達する時間や、PsychoPyが「刺激を画面に描画せよ」という命令を実行してから、実際にそれがモニターに伝わって画面に表示されるまでの時間です。これらの値もやはりハードウェアやOS、デバイスドライバに依存するので一概に言えないのですが、「ゲーム用」などと謳われている高性能なキーボードやモニターでなければ、数十ミリ秒もの時間を要することも珍しくありません。 - 先行研究の結果と比較して平均反応時間が十数ミリ秒にわたってずれている場合は、機材が原因である可能性も考慮する。可能であれば先行研究と同一条件の追試を行っておき、そこで大きなずれがないか確認しておくことが望ましい。 - 複数の実験参加者を呼んで並行して実験を行う場合、実験に使用するハードウェアやソフトウェアは可能な限り統一する。 といった点を守っておけば、多くの実験において時間計測の精度が大きな問題となることはないと思います。 .. _topic-suppress-onoff-time: コンポーネントの開始・終了時刻をデータファイルに出力しないようにする ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 刺激やキーボードといったコンポーネントの開始・終了時刻をデータファイルに出力する機能は、何か実験中に問題が生じた場合に、どの時点で生じたのかを知る重要な手がかりを与えてくれます。しかし、ルーチン内に配置されているがコンポーネントが多い場合、コンポーネント数に応じてデータファイルの列数が増えてしまうため、非常にデータファイルが見難くなる場合があります。 開始・終了時刻の出力を抑制するには、各コンポーネントのプロパティ設定ダイアログの「データ」タブにある **[開始・終了時刻の保存]** のチェックを外します( :numref:`fig-savestartstop-uncheck` )。チェックを外したコンポーネントだけが出力されなくなりますので、実験の流れを把握する上で重要なコンポーネントだけチェックを残して他はチェックを外すとよいでしょう。 .. _fig-savestartstop-uncheck: .. figure:: fig03/savestartstop-uncheck.png :width: 60% **[開始・終了時刻の保存]** のチェックを外すとそのコンポーネントの開始・終了時刻が出力されなくなります .. _topic-summaries-datafiles: 「CSV形式のデータを保存(summaries)」・「xlsx形式のデータを保存」で作成される記録ファイルの形式 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 本文で述べた通り、これらの記録ファイルでは条件ファイルで記述された条件ひとつにつき1行に結果が要約されています。最初にパラメータが出力され、続いて繰り返し数が出力されていることも本文で述べました。ここではさらにその右側に数百列にわたって出力されている内容について解説します。 これらの情報は、実験内で用いられているコンポーネント毎にまとまっています。本章の実験では(教示などの追加前であれば)Polygonコンポーネントが2つ(cross, stimulus)とKeyboardコンポーネント1つ(key_resp_2)が使用されているので、これらのコンポーネント毎にまとまっているはずです。出力される情報はコンポーネントにより異なります。表 :numref:`tbl-stimulus-component-output` にPolygonコンポーネントが出力する情報を示します。 .. _tbl-stimulus-component-output: .. csv-table:: Polygonコンポーネントの出力(**[名前]** はcrossとする) :header: "列名", "概要" :widths: 30, 70 cross.started_mean,刺激の開始時刻の平均値を計算したもの。単位は秒。 cross.started_raw,刺激の開始時刻を試行順に並べたもの。単位は秒。列数は繰り返し数に一致し、1列目にのみ列名が付く。 cross.started_std,刺激の開始時刻の標準偏差を計算したもの。単位は秒。 cross.stopped_mean,刺激の終了時刻の平均値を計算したもの。単位は秒。ただし、刺激の終了時刻が指定されていない場合は列自体が出力されない。 cross.stopped_raw,刺激の終了時刻を試行順に並べたもの。単位は秒。列数は繰り返し数に一致し、1列目にのみ列名が付く。刺激の終了時刻が指定されていない場合は空白となる。 Polygonコンポーネントからは、刺激の開始・終了時刻のrawデータ、つまり統計処理などをする前の「生」のデータと、平均値と標準偏差が出力されています。rawデータならともかく、平均値や標準偏差にはあまり意味がないので、利用することは少ないと思います。Polygonコンポーネント以外の刺激提示用のコンポーネントはほぼ同様の情報を出力します。 続いてKeyboardコンポーネントが出力する情報を表 :numref:`tbl-keyboard-component-output` に示します。Polygonコンポーネントの出力と似たようなレイアウトですが、最初に正答率と各試行の正誤に関する情報( **[正答を記録]** を選択した場合のみ)、平均反応時間、各試行の反応時間、反応時間の標準偏差が出力されています。これらの情報が出力されていることに魅力を感じるなら、trial-by-trial記録ファイルではなくxlsx形式(またはCSV形式のsummaries)の出力ファイルを使うとよいでしょう。 .. _tbl-keyboard-component-output: .. csv-table:: Keyboardコンポーネントの出力(**[名前]** はkey_resp_2とする) :header: "列名", "概要" :widths: 30, 70 key_resp_2.corr_mean, 正答率を計算したもの。 **[正答を記録]** を選択した場合のみ出力される。 key_resp_2.corr_raw,試行順に正答なら1、誤答なら0を並べたもの。列数は繰り返し数に一致する。1列目にのみ列名が付く。 **[正答を記録]** を選択した場合のみ出力される。 key_resp_2.keys_raw,押されたキーを試行順に並べたもの。列数は繰り返し数に一致する。1列目にのみ列名が付く。 key_resp_2.rt_mean,キー押し時刻の平均値を計算したもの。単位は秒。 key_resp_2.rt_raw,キー押し時刻を試行順に並べたもの。列数は繰り返し数に一致する。1列目にのみ列名が付く。単位は秒。 key_resp_2.rt_std,キー押し時刻の標準偏差を計算したもの。単位は秒。 key_resp_2.started_mean,キー押し検出開始時刻の平均値を計算したもの。単位は秒。 key_resp_2.started_raw,キー押し検出開始時刻を試行順に並べたもの。単位は秒。列数は繰り返し数に一致し、1列目にのみ列名が付く。キー押し検出開始時刻が指定されていない場合は空白となる。 key_resp_2.started_std,キー押し検出開始時刻の標準偏差を計算したもの。単位は秒。 key_resp_2.stopped_mean,キー押し検出終了時刻の平均値を計算したもの。単位は秒。ただし、キー押し検出終了時刻が指定されていない場合は列自体が出力されない。 key_resp_2.stopped_raw,キー押し検出終了時刻を試行順に並べたもの。単位は秒。列数は繰り返し数に一致し、1列目にのみ列名が付く。キー押し検出終了時刻が指定されていない場合は空白となる。 key_resp_2.stopped_std,キー押し検出終了時刻の標準偏差を計算したもの。単位は秒。ただし、キー押し検出終了時刻が指定されていない場合は列自体が出力されない。 すべてのコンポーネントについて情報が出力された後にはorderという見出しがついた列があり、その列を1行目と数えて繰り返し数と同じだけの列数の出力があります。これは各条件の1試行め、2試行め…が実験全体の中で何試行めであったかを示しています。最初の試行が0番目と出力される点にご注意ください。以上で出力は終了です。 コンポーネントひとつにつき開始時刻・終了時刻の情報だけで繰り返し数×2+αの列数が出力されるので、繰り返し数が100回以上、コンポーネント数が十数個もあるような実験を作ると軽く1000列を越えるファイルが出力されてしまいます。これだけ列数が多いと必要な情報を探すのが大変なので、あまり実用的ではないというのが筆者の考えです。ただ、「 :numref:`{number}:{name} ` 」で述べた方法で開始・終了時刻を保存しないようにすると、開始・終了時刻に関する情報がごっそりなくなってKeyboardコンポーネントの反応の正誤、反応時間の出力とorderの情報だけになります。これならかなり実用的になるかと思います。 最後に「xlsx形式のデータを保存」と「CSV形式のデータを保存(summaries)」の使い分けですが、これは分析に使用するアプリケーションが対応できる形式のものを選ぶとよいでしょう。一般論として、CSV形式のデータはただのテキストファイルなので数多くのアプリケーションで開くことができますが、条件ファイルのパラメータに日本語が含まれていると正常に表示されない場合があります。xlsx記録ファイルは開くためにExcelやLibreOffice Calc等が必要ですが、日本語を含んでいても正常に表示できます。各自の都合に合わせて選んでください。 .. _topic-routine-templates: ルーチン新規作成時のテンプレート機能について ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ PsychoPy 2022.1より、ルーチンの新規作成時にあらかじめ「心理学実験にありがちな」画面を作成するためのコンポーネントが配置されたルーチンを作成する「テンプレート機能」が追加されました。 :numref:`fig-routine-template` のように、ルーチンの新しい名前を決定するダイアログに **[Routineのテンプレート]** という項目が表示され、新しいルーチンに適用するテンプレートを選ぶことができます。 .. _fig-routine-template: .. figure:: fig03/routine-template.png :width: 50% 新規ルーチン作成時のテンプレート選択。 便利な機能だとは思いますが、テンプレートを適用した後に手作業で設定しないといけない項目があったり、テンプレートの機能を活かすためにその前のルーチンで適切な前処理をしておかないといけなかったりするなど、Builderの初心者の方がいきなり使いこなせるものではないと思います。そのため、本書ではコンポーネントが何も配置されていない「Basic:blank」というテンプレートを使うという前提で解説していきます。 **[Routineのテンプレート]** は初期状態で「Basic:blank」となっているので、変更せずに **[新しいRoutineの名前]** だけ入力してOKボタンをクリックして作業を進めてください。