.. title:: Pythonで心理実験 - 例題23-1 例題23-1:チュートリアルワークショップ@JPA78ご報告 ============================================================ **A:** さてさて、今年も性懲り無くチュートリアルワークショップ(以下TWS)をしたSを迎えて反省会ですよ。まずはお疲れさん。 **S:** うへー。へろへろ。 **B:** ささ、お茶でもどうぞ。 **S:** あ、ありがとうございます。んぐんぐ。ぷはー。 **A:** で、どうよ。今回の首尾は。 **S:** んー。ちょっと無理して話題を詰め込みすぎたかなあ。TWSの企画をsubmitした時にはもっと内容を少なくして皆さんに作業してもらうつもりやったんよね。去年のTWSが一方的にしゃべるだけの内容で、他のTWSで「実際にPCで実習できてよかった」って感想が出てんのを見て反省したんで。 **A:** うむ。そう言ってたな。 **S:** でも、PsychoPy Builderのテキストを公開して、そっちを参照してくださいって言えるようになったんで、そうしたら内容が薄いより盛りだくさんな方がええかなと思って…。結局実習してもらえる時間がほとんどなかった。 **A:** 10分くらいしかなかったな。 **S:** 迷走してしまった。わざわざノートPCを持ってきてくださった皆さんに申し訳ない。 **A:** まあ仕方ないんでないの。発表資料を見た時には絶対実習時間ないと思ったもんね。あんた普段スライド1枚に3分くらいかけるのに80分の枠で30枚もスライドあったやろ。 **S:** ううう。 **A:** ま、終わったことはもう仕方ないんで報告しろよ。 **S:** うい。今回は「 **PsychoPy Builderにおける 実験の動的な制御の方法** 」というタイトルで、PsychoPy Builderに話題を絞って話をしました。Builderを使っていて「ああ、○○が出来たらいいのに!」と思った時にもしかしたら役に立つかもしれないテクニックの紹介です。 **B:** …Sセンセ、エセ大阪弁じゃないんですね。Aさんと区別しにくい。 **S:** あー。なんちゅうかな。話す内容とかによって楽なしゃべりかたってもんがあるんよ。こういう話をするとエセ標準語っぽいしゃべりかたになってまうねん。 **A:** エセ大阪弁とか言われていることに反論はないのか。 **S:** 一応大阪出身やけど、もうあちこち引っ越しして言葉が混じってしもうて自分でも何弁しゃべっとんのかわからへんからね。で、内容やけどスライドはこちら。 .. figure:: img/23-1-01.png `TWSスライド(修正版)のPDFファイルへのリンク `_ **S:** 紹介したテクニックは6つ…と言いたいところだけれども、案の定6個目の「時間があれば」の項目は時間がなかったので終了。 #. Builderの内部変数を利用する #. ExpInfoダイアログの値を利用する #. オブジェクトのデータ属性を利用する #. if文を用いて処理を分岐する #. ルーチンを中断する #. オブジェクトのメソッドを利用する(時間があれば) **A:** 改めていうけど、80分でやるのは無謀よな。 **S:** ううう。 **A:** スライドの中で出てくる作業01から作業07を実際に作成したファイルがこちら。 + `sample01.psyexp `_ + `sample02.psyexp `_ + `sample03.psyexp `_ + `sample04.psyexp `_ + `sample05.psyexp `_ + `sample06.psyexp `_ + `sample07.psyexp `_ **B:** 他にも配布資料ありませんでした? **S:** ああ、あれは例題24で紹介する予定の `「PsychoPy Builderで作る心理学実験」 `_ というPDF文書からの抜粋だから、別の例題として改めて取り上げようと思います。あの資料についても内部変数しか触れることが出来なかった…うぅ。 **A:** なんか補足しときたいことある? **S:** TWSでは内部変数とデータ属性というのを紹介したんやけど、追加資料の最後の2ページは内部変数の一覧。これはTWSの中でも簡単に触れました。他にはKeyboardコンポーネントやループ(TrialHandler)のデータ属性などを載せてます。KeyboardコンポーネントのkeysやTrialHandlerのthisNなんかが載ってます。 **B:** ふんふん。 **S:** 他には、時間があれば紹介したかった「メソッド」の例が少しだけ載っています。メソッドはものすごくたくさんあるので紹介しているのはあくまで少しだけ。例題が無いと意味不明だと思いますのでぜひ `「PsychoPy Builderで作る心理学実験」 `_ を見ていただければと思います。第3章から第10章で具体的な実験を作成しながら解説してあります。 **A:** とりあえず補足としてはそんなもんかね。んじゃ、参加者の皆さんからの質問などについてどーぞ。 **B:** え、スライドの内容とか解説してくんないんですか。 **S:** それはTWSのご報告としてではなく改めて取り上げたいと思います。それでは最初の話題。 作業5(sample05.psyexp)がスライド通りに作っても動かないんだけど ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ **A:** ふっ、実演でエラーを起こした恥ずかしい件だな。 **S:** うるさい。これは結論としてはfeedbackルーチンのCodeコンポーネントをTextコンポーネントより上に配置しないといけないことをスライドに書いていなかったのが問題でした。上記のリンクからダウンロードできるスライドでは注を入れてあります。 .. figure:: img/23-1-02.png **B:** TWS前から公開していた `sample05.psyexp `_ ではちゃんとなっているんですね。 **A:** 変数messageをfeedbackルーチンのBegin Routineで指定するからこんな凡ミスするんじゃねーの? trialルーチンのEnd Routineで指定しろよ。 **S:** いや、それはごもっともなんやけど、スライドの「作業5」(21枚目)の一番下に「ポイント」として書いたように、 **trialルーチンに置いたKeyboardコンポーネントのデータ属性にfeedbackルーチンからアクセスできる** っちゅーことをこのデモでは示しときたかってん。言いかえれば **各コンポーネントの名前はグローバルなものであり、実験のどこからでもアクセスできる** っちゅーことで、このことを知らないと無用なトラブルに巻き込まれたり、逆に知っているとうまく利用したりすることが出来るやろ。 **A:** んー。それって実際に困る場面と利用できる場面を示さないとわかんないんじゃないの? **S:** そう、それよ。ムズいよな。その辺をじっくり説明する代わりに話題がそれしかないTWSと、今回みたいにいろんなテクニックを次々と紹介するTWSとどっちがええと思う? **A:** 私に聞くなよ。じゃ、この件はこのくらいにして次行くか。 **B:** あのー、せめてCodeコンポーネントを上にしておかないとなぜエラーになるのかくらいは解説した方がいいんじゃないですか? **S:** おお、B君ええこと言うやん。えーと、Builderでは、同一ルーチン上に並んでいるコンポーネントは上から下へ順番に実行されます。ですから、CodeコンポーネントよりTextコンポーネントが上にあると、Codeコンポーネントによって変数messageに値が設定される前にTextコンポーネントの処理が行われてしまいます。Codeコンポーネントを上に移動させると、変数messageが設定されてからTextコンポーネントの処理が行われます。 **A:** プログラムを自分で書く人にとってはイメージしやすいと思うんだけど、いきなりPsychoPy Builderを使う人にとってはどうなんだろうなあ。 作業2(sample02.psyexp)などで文字列に u がついているのは何? ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ **A:** これは我らが「Pythonで心理実験」ですでに何度も触れてるんだがなあ。UnicodeのUです。 **S:** こらこら、そんな口の利き方すんな。感じ悪くなるやろ。TWSに参加して下さった皆さんは別に「Pythonで心理実験」なんて見たことない人ばかりだろうし。 **B:** えっ、誰も見てくださっていないんですか! **S:** いや、実際何人くらいの方々が見てくださってるんかなんて知らんがな。ともかくあんたらちょっと黙っとれ。えー、ごほん。コンピューター上で日本語などの様々な言語の文字を表現するためのUnicodeというものがありまして、PythonではUnicodeの文字列を指定する時には文字列の先頭にuを付けなければいけません。日本語英語交じりの文も u を付ければ問題なく表示できますし、別に英語文字列に u を付けても問題は生じません。 **A:** ひとつ追加。Unicodeかどうかを意識しないといけないのは文字列をPythonの式として記述しないといけない場合だけであることにご注意ください。Textコンポーネントでスクリーンに表示したい文字列を直接入力する場合はPythonの式ではないのでuも ' 'も付けずに入力します。プロパティがPythonの式として評価されるか否かは… **B:** プロパティ名の末尾に $ があるかどうかで判断すればいいんですよね! $が無ければ直接入力です! $が無いプロパティにPythonの式を入力するには$を先頭に付ければOKです。 .. figure:: img/23-1-03.png **S:** おお、呼吸ばっちりやね。さすが師弟、すばらしい。 **B:** えっ、いやー、それほどでも。照れるなー。げへへ。 **A:** (なんとも言えない表情でSとBを交互に見ながら)…こんなことを言われてB君が喜ぶのは意外だ。 **B:** なにを言うんですか―。こんなにもAさんを慕っているというのに。 **A:** …ちょっとB君、こっちへ来なさい。Sよ、すまんが一人で進めておいてくれ。 **S:** あいよー。 パラメータに日本語を使った場合、Excelで実験記録ファイルを開くと文字化けして大変なことになるんですが。 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ **S:** これは例題 :doc:`19-4 <19-4>` で取り上げた問題ですね。CSV形式で実験結果を出力してExcelで開くときに、実験結果にUnicode文字列が含まれていると文字化けしてしまいます。 詳しくは例題 :doc:`19-4 <19-4>` をご覧ください。結論だけ言っておくと、xlsx形式の実験記録ファイルを出力すればExcelで正しく開くことが出来ます。LibreOffice CalcであればCSV形式のままでも開くことが出来ます。すでにCSV形式で保存してしまった記録ファイルをどうしてもExcelで開きたい場合は、記録ファイルの拡張子をtxtに変更して、Excelのテキストファイルウィザードで読み込むと文字化けせずに開くことができます。 .. figure:: img/23-1-04.png 複数画面にわたる文章A、B、C、…を無作為な順に読ませるにはどのようなループを組めばよいでしょう? ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ **S:** つづいてこちらのご質問。ちょっと上記のタイトルだけじゃわかりにくいと思うので、簡単に実験の流れを。一画面には入りきらない文章A、B、C、…があって、実験参加者はスペースキーを押して文章を送りながら読み進めます。当然のことながら、これらの文章の提示順序は固定されています。それで、文章A、B、C、…がどの順番に提示されるかは参加者毎に無作為に選択されるものとします。よろしいでしょうか。 .. figure:: img/23-1-05.png **S:** このように無作為に選択するパラメータと固定順序のパラメータが混在している場合は、多重ループを組むのが有効です。文書A、B、C、…毎にxlsxファイルを作成し、これらのxlsxファイル名を列挙したxlsxファイル(stories.xlsx)を作成します。 下図のようにループを二重に組んで、外側のループでstories.xlsxを読み込んで変数story_fileにxlsxファイル名を設定します。そして、内側のループではconditionsFileに$story_fileを指定すれば、外側のループによって設定されたxlsxファイルを読み込みます。外側のループを繰り返し回数1回でrandom、内側のループを繰り返し回数1回でsequentialにすれば、目的を達成することができます。 .. figure:: img/23-1-06.png **A:** ふう、やれやれ。Sよ。これはサンプルファイルをダウンロードできるようにしておいた方が良いのではないか。 **S:** もちろん。以下のリンクからサンプルをダウンロードしてください。多重ループについての詳しい解説は `「PsychoPy Builderで作る心理学実験」 `_ の第4章をご覧ください。 `サンプルファイル (23-1.zip) `_ **A:** それにしても何故に「坊っちゃん」に「吾輩は猫である」? **S:** んー? このあたりのテキストなら著作権切れてると思って。それに一応愛媛県在住やし。次、行こうか。 外部機器との入出力はどの程度できますか? ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ **S:** BuilderにはParallelOutコンポーネントというコンポーネントがあります。こいつを使うとパラレルポートからトリガーを出力することができます。 **A:** 逆にいうとそれだけしかないけどな。 **S:** んー。Builderの標準コンポーネントの範囲ではこれだけかなあ。Codeコンポーネントを使うならば、PsychoPyにはpsychopy.serialというモジュールがあるのでシリアルポートからの入出力が出来る( :doc:`例題22-2 <22-2>` )。あとは :doc:`例題9-1 <09-1>` 、 :doc:`9-2 <09-2>` 、例題 :doc:`21-1 <21-1>` 、 :doc:`21-3 <21-3>` で扱っているctypesを使って共有ライブラリの関数を呼び出す方法がある。 **A:** ま、ctypesはC/C++である程度プログラムが書ける知識がないとしんどいけどな。 **S:** そこでお勧めなのが拙作の `pyAPISUBP `_ ですよ(鼻息)。例題21-1、21-3で扱ったContecのUSB接続I/Oユニットをpythonから利用するパッケージです。C/C++を知らなくても大丈夫!まだベータ版ですが… **A:** 宣伝乙。そのpyAPIUSBPにしてもCodeコンポーネントを通じてBuilderから呼び出すpythonスクリプトが書けないと使えないわけだが。 **S:** カスタムコンポーネントを誰か作ってくれればいいんだけどね…。あ、まだ解説したことはありませんがBuilderでは自作のコンポーネント(=カスタムコンポーネント)を追加して利用することができます。 **A:** ( **「おめーが作れよ」** という無言の圧力) **S:** …言われんでもわかっとるわい。今度リリースされる1.81系ではカスタムコンポーネントの書き方がちょっと変わるから、それまでカスタムコンポーネントがらみの仕事は様子を見てるんだっての! **A:** ほう。ならば1.81.00がリリースされたら対応する気なんだな? **S:** (遮るように大きな声で)はい、ほな次行きましょうか。次。 OS上で動くのだから時間的な遅延があるのではないですか? ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ **A:** うーん、これはタフな質問だったな。 **S:** PsychoPyはOS上で動くアプリケーションだから、OSから干渉を受けて刺激の表示や反応の取得に遅延が生じるんじゃないかというご質問だったのですが、それは「あります」としか答えようがありません。これは別にPsychoPyに限った話ではなく、PsychToolboxなどにも共通する問題ですし、現代的なマルチタスクOSを使う限り、自作でCやらアセンブリ言語で書こうが逃れ得ない問題です。 **A:** MS-DOSのような昔のOSが仮に今のPCで動いたとしても、周辺機器のドライバがないからな。ドライバから自分で書くというのは非現実的だし。 **S:** 遅延があることを前提としたうえで、その遅延が問題とならないように実験を計画したりデータの分析方法を決めたりするしかないと思うんですよ。そうでなければ、OSから独立して制御できる特殊なハードウェアを使うとか。 **A:** 高い時間精度が求められる実験はBuilderで作るお手軽実験の守備範囲じゃないってこったな。 **S:** いや、そこまで言うとBuilderを貶めすぎで。Builderはちょっと可読性の低いコードを吐くけど時間的精度で安易な妥協はしてへんねん。だから、現代のPC、現代のOS、現代のマルチメディアライブラリ(OpenGL等)上で望める程度の時間精度は得られるんや。だから、Builderの時間精度がお話にならないというのなら、お手軽さか、手間か、お金か、何かを犠牲にせんといかん。 **A:** んー。Builderほどお安くお手軽にいかないってのは、そりゃその通りだろうね。 **S:** ご質問に対する適切な回答になっているか自信がありませんが、このくらいでご勘弁ください。 *------------------------------ * * * ------------------------------* **S:** さて、TWSでいただいた主なご質問はだいたいお答えしたと思います。あとアイトラッカーとの連携に関するご質問などもいただきましたが、これは難しい話題なので、またいつか機会を改めて取り上げたいと思います。 **A:** ん。ごくろーさん。相変わらず反省すべき点は多いけど、トーク下手なSならこんなもんじゃないの。 **S:** なんかね、ダメなんよ。ポスドクん頃よりさらに駄目になった。 **A:** 落ち込んでないでとにかくお茶でも飲めよ。 **S:** おう。いただきます。…って、あれ? B君は? **A:** うるさいのでさっき連れ出した。奴は生八ッ橋に目がないからな。そこにあった生八つ橋を廊下に並べて、学食まで誘導した。 **S:** おい、そこにあった生八ッ橋って、家族へのお土産に買っといた奴…! **A:** おっと。もうこんな時間じゃないか。もう実験参加者が控室に来てる頃だわ。急いでいかないと。お代はBくんに請求してね。んじゃ、また!(ものすごい勢いで走り去る) **S:** ちょっと、こら!…っと! (急に立ち上がったらノートPCを落っことしそうになって慌てて掴む) はぁ、危ねえ危ねえ。 **B:** (Aと入れ違いで部屋に入ってきて)ぷはー、おいしかったー。いやいやいや。なんだかAさんが慌てて出ていきましたけど、どうしました? **S:** ほう。これはいいところへ来たね。B君。少し話をしようか。 **B:** はいはい。なんでしょう? *------------------------------ 以下自粛 ------------------------------*