はじめに
-
5年ほど前に以下のような質問が黒木先生宛にきていました。
-
どうやら, jsPsychでの実験中にpie chartといったグラフを提示しようという試みのようです。今更感はありますが,今回はサンプルコードを書いてみました。
-
webブラウザ上でグラフを提示するにはchart.jsライブラリというものが簡便かつ美しく表示できるので,こちらを利用します。
-
chart.jsを使用するには
<canvas>
タグを利用する必要があります。jsPsychでは<canvas>
を利用する際にはcanvas-button-responseやcanvas-keyboard-responseといったプラグインを用いるのが有用ですので,その利用方法について簡単にまとめます。
chart.js
-
chart.jsはJavaScriptでグラフ(chart)を表示するためのライブラリです(https://www.tohoho-web.com/ex/chartjs.html)
-
単純な棒グラフや線グラフだけでなく,多くの形式でグラフを作成することができます。
-
htmlで段落を示すには
<p>
タグを用い,画像を提示するには<img>
タグを用いるのと同様に,四角や円といった図形を表示するには<canvas>
タグを利用します。 -
<canvas>
タグは単純な図形を表示するだけなら簡単ですが,複雑な図形を描くのはかなり大変です。 -
グラフを
<canvas>
上で簡単に書けるようにしたライブラリがchart.jsです。 -
利用するためには,jsPsychでプラグインを事前に読み込むのと同様に,chart.jsライブラリを読み込んでおく必要があります。オンラインであれば,以下のようにして読み込みます。
<script src="https://unpkg.com/@jspsych/plugin-html-button-response@1.1.2"></script>
<script src="https://cdn.jsdelivr.net/npm/chart.js@3.9.1/dist/chart.min.js"></script> // こいつがchart.jsの読み込み
<script src="https://unpkg.com/@jspsych/plugin-canvas-button-response@1.1.2"></script>
jsPsychにおける<canvas>
- jsPsychにおいて課題中に図形を表示させるには,canvas-button-responseやcanvas-keyboard-responseプラグインを用いるのが一般的です。
- 黒木先生が開発したjspsych-psychophysicsも有用です。
- https://jspsychophysics.hes.kyushu-u.ac.jp/
- canvas-button-responseの使い方は公式サイトから確認してください。(https://www.jspsych.org/7.3/plugins/canvas-button-response/)
公式サイトのデモ
- canvas-button-responseプラグインの使用方法は公式サイトにデモがあります。以下のようなコードを書きます。
function filledCirc(canvas, radius, color) {
var ctx = canvas.getContext("2d");
ctx.beginPath();
ctx.arc(150, 150, radius, 0, 2 * Math.PI);
ctx.fillStyle = color;
ctx.fill();
}
var circle_1 = {
type: jsPsychCanvasButtonResponse,
stimulus: function(c) {
filledCirc(c, 100, 'blue');
},
canvas_size: [300, 300],
choices: ['Red', 'Green', 'Blue'],
prompt: '<p>What color is the circle?</p>',
data: {color: 'blue', radius: 100}
};
- このプラグインでは,図形を描くfunctionを事前に作成し(filledCirc),それをcanvas-button-responseで表示するという流れになります。
- この事前に作成するfunctionでグラフに関する命令を書きます(chart.js)
サンプルコード
-
今回は実験課題中のFキーとJキーを押した回数とそれぞれの平均反応時間をグラフ化してみます。
- キー押し回数は円グラフ,反応時間は棒グラフで描画します。
-
例えば,pie chartを表示するには,以下のようなコードを書きます。
function piechart(c, F, J) {
var ctx = c.getContext("2d");
let pieConfig = {
type: 'pie',
data: {
labels: ['Fkey','Jkey'],
datasets: [{
label: 'キー押し回数',
data: [F, J], ///F, Jにはそれぞれ,課題中にFキー,Jキーを押した回数が格納されています
backgroundColor: [
'#ff0000',
'#0000ff',
]
}]
},
};
let pieChart = new Chart(ctx, pieConfig);
}
-
この
type
の部分をbar
に変えれば,棒グラフになります。- chart.jsの基本的な書き方は日本語でも多くの記事があるので,参考サイトには困らないと思います。
-
どのようなデータを用いるのかはjsPsych APIでデータを抽出し,計算すれば良いです。
Demoとコード
-
以下のURLで円グラフと棒グラフを表示するデモを実施することができます。
-
実際のコードは以下です。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>My experiment</title>
<script src="https://unpkg.com/jspsych@7.3.3"></script>
<link href="https://unpkg.com/jspsych@7.3.3/css/jspsych.css" rel="stylesheet" type="text/css" />
<script src="https://unpkg.com/@jspsych/plugin-html-keyboard-response@1.1.2"></script>
<script src="https://unpkg.com/@jspsych/plugin-html-button-response@1.1.2"></script>
<script src="https://cdn.jsdelivr.net/npm/chart.js@3.9.1/dist/chart.min.js"></script>
<script src="https://unpkg.com/@jspsych/plugin-canvas-button-response@1.1.2"></script>
</head>
<body></body>
<script>
/* initialize jsPsych */
const jsPsych = initJsPsych({
on_finish: function () {
jsPsych.data.displayData();
}
});
const timeline = [];
const ins = {
type: jsPsychHtmlButtonResponse,
stimulus: '<p>Demoを始める。</p>',
choices: ['Start']
};
const fix = {
type: jsPsychHtmlKeyboardResponse,
stimulus: '',
choices: "NO_KEYS",
trial_duration: 1000
}
const trial = {
type: jsPsychHtmlKeyboardResponse,
stimulus: "<p>FかJのどちらかを入力してください。</p>",
choices: ["f", "j"],
data: {
task: 'response'
},
on_finish: function (data) {
data.Fkey = jsPsych.pluginAPI.compareKeys(data.response, 'F');
data.Jkey = jsPsych.pluginAPI.compareKeys(data.response, 'J');
}
};
const procedures = {
timeline: [fix, trial],
repetitions: 10,
on_finish: function () {
trials = jsPsych.data.get().filter({ task: 'response' });
Fkey_trials = trials.filter({ Fkey: true });
Jkey_trials = trials.filter({ Jkey: true });
FkeyCount = Fkey_trials.count();
JkeyCount = Jkey_trials.count();
Frt = Math.round(Fkey_trials.select('rt').mean());
Jrt = Math.round(Jkey_trials.select('rt').mean());
}
};
function piechart(c, F, J) {
var ctx = c.getContext("2d");
let pieConfig = {
type: 'pie',
data: {
labels: ['Fkey','Jkey'],
datasets: [{
label: 'キー押し回数',
data: [F, J],
backgroundColor: [
'#ff0000',
'#0000ff',
]
}]
},
};
let pieChart = new Chart(ctx, pieConfig);
}
function barchart(c, F, J) {
var ctx = c.getContext("2d");
let barConfig = {
type: 'bar',
data: {
labels: ['Fkey','Jkey'],
datasets: [{
label: '平均反応時間(ms)',
data: [Frt, Jrt],
backgroundColor: [
'#ff0000',
'#0000ff',
]
}]
},
};
let barChart = new Chart(ctx, barConfig);
}
var chart1 = {
type: jsPsychCanvasButtonResponse,
stimulus: function(c) {
piechart(c, FkeyCount, JkeyCount)
},
canvas_size: [500, 500],
choices: ['棒グラフに進む'],
prompt: '<p>キー押し回数のpie chartはこんな感じ</p>'
};
var chart2 = {
type: jsPsychCanvasButtonResponse,
stimulus: function(c) {
barchart(c, Frt, Jrt)
},
canvas_size: [500, 500],
choices: ['終了する'],
prompt: '<p>それぞれのキー押しの平均反応時間はこんな感じ</p>'
};
timeline.push(ins, procedures, chart1, chart2);
jsPsych.run(timeline);
</script>
</html>
- いつかもう少し丁寧に書くかもしれません。