Cómo programar fácilmente experimentos comportamentales online utilizando jsPysch

Gustavo Juantorena
11 min readAug 10, 2020

--

Este es la primer de una serie de notas relacionadas a la creación de experimentos on line utilizando la biblioteca jsPsych en el lenguaje JavaScript.

Pueden ver la segunda entrega acerca de como subir su experimento a internet fácil y gratis entrando a este link.

La pandemia del COVID-19 ha dificultado el normal funcionamiento de muchas actividades y la ciencia experimental no ha estado exenta.

A pesar de que en algunas áreas de la ciencia se hace imposible continuar realizando experimentos (no podemos llevarnos los ratones a nuestras casas), aquellas personas que se dedican a estudiar el comportamiento o las diferentes funciones cognitivas en humanos pueden encontrar una herramienta muy útil en los experimentos on line.

Esta modalidad se basa en programar una o más tareas en una computadora y subirlas a internet para que los voluntarios puedan realizarlas desde sus casas, sin tener que ir a un laboratorio. En base a estos datos recolectados se puede poner a prueba hipótesis científicas de lo más diversas. Entre sus ventajas se encuentran la posibilidad de acceder a una muestra más grande y diversa de personas, aunque con la desventaja de tener menor control experimental.

Si bien en los comienzos este tipo de experimentos resultaban limitados a personas con ciertos conocimientos de programación y el tipo de tareas se cernían a mediciones de tiempo de reacción u otras variables sencillas, hoy en día existen un amplia variedad de herramientas para generar experimentos con un alto grado de sofisticación y subirlos fácilmente a internet, de manera rápida y gratuita.

A pesar de que existen opciones para realizar experimentos sin tener que programar una sola línea de código (por ejemplo Psychopy Online ), en mi opinión codear el experimento proporciona una flexibilidad mucho mayor.

En este caso me voy a centrar en una biblioteca llamada jsPsych dentro del lenguaje de programación JavaScript. Mi elección se basa principalmente en tres razones:

  • JavaScript es el lenguaje con el que se habla con los navegadores, lo que facilita mucho la interfaz con el usuario en un contexto web.
  • Resulta bastante sencillo lidiar con el backend, es decir la comunicación con el servidor donde estará alojado nuestro experimento, ya que al fin y al cabo va a ser algo así como una pagina web y ya hay mucho trabajo realizado al respecto.
  • jsPsych tiene una comunidad de desarrolladores en crecimiento y con mucha iniciativa. Tal es así que han surgido plataformas como cognition.run que se hacen cargo en un cien por ciento de la comunicación con el servidor. Vale aclarar que un requisito es que el experimento esté hecho específicamente en javascript utilizando jsPsych.

Para el tutorial me basaré en el oficial de la biblioteca, realizando modificaciones cuando considere que así queda más claro y/o es más divertido.

Paso 1

Para comenzar debemos descargarnos la última version de jsPsych desde su repositorio en github (al momento de publicar esto es la V6.1.0 pero lo importante es que sea la que nos aparece arriba de todo).

Luego vamos abajo de todo y nos descargamos el archivo zip de nuestra versión.

Finalmente crean una carpeta con el nombre del experimento que quieran hacer y lo descomprimen allí. Así se vería en Windows, pero jsPsych es compatible con cualquiera de los sistemas operativos más populares.

Paso 2

Nos descargaremos un entorno de desarrollo integrado (o IDE, por sus siglas en inglés) que nos servirá para escribir código de manera más fácil y prolija.

Mi recomendación en este caso es el Visual Studio Code ya que es gratuito, fácil de usar y suficientemente potente para nuestras necesidades, pero hay muchas otras buenas opciones como atom o sublime.

Paso 3

A continuación debemos crear un archivo HTML que será el lienzo de nuestro experimento. Para ello abriremos el IDE que hayamos decidido descargar en el paso anterior y como si fuera el bloc de notas pasaremos a escribir un código básico que prácticamente todos los archivos HTML tienen en común:

<!DOCTYPE html>
<html>
<head>
<title>Mi experimento</title>
</head>
<body></body>
</html>

Lo guardamos con el nombre experimento.html en la carpeta que creamos en el paso 1. Lo único que hicimos fue crear una página en blanco cuyo encabezado es Mi experimento.

Paso 4

Importamos la biblioteca jsPysch y también los estilos de CSS que vienen con la biblioteca, los cuales nos permirán darle un formato más agradable a la vista a nuestros experimentos:

<!DOCTYPE html>
<html>
<head>
<title>Mi experimento</title>
<script src="jspsych/jspsych.js"></script>
<link href="jspsych/css/jspsych.css" rel="stylesheet" type="text/css"></link>
</head>
<body></body>
</html>

Noten que utilizamos las etiquetas (o tags) <script> para designar que algo es código escrito en JavaScript, <link> para CSS y <html> para lo que está en ese lenguaje de marcado.

Ahora llegó el momento de explicar la estructura general de un experimento en jsPysch. Básicamente primero tenemos que importar todo lo que vayamos a necesitar. En este caso importamos la biblioteca y los estilos CSS pero nos falta algo clave que son los plugins.

Los plugins se pueden pensar como las tareas que van a estar incluidas en nuestro programa y es este formato modular el que hace que jsPsych sea relativamente sencillo y muy flexible. Los mismos tienen una estructura particular y poseen tanto parámetros comunes (como por ejemplo el tiempo de inicio y finalización del ensayo o un objeto llamado data que almacena información) como propios de cada uno.

Algunos ejemplos de plugins que vienen con la biblioteca (y que ya tenés descargados!) incluyen la presentación de estímulos visuales estáticos, sonoros o incluso videos, tareas clásicas de tiempo de reacción o de memoria, entre muchas más que se pueden ver acá en la documentación oficial. Es importante siempre tener en cuenta qué parámetros requiere cada uno para poder ser utilizados. Por ejemplo, si es un plugin que muestra un texto seguramente requiera un parámetro con un nombre particular que incluya ese texto que vamos a presentar. Esa información se encuentra en la documentación.

Por otro lado cualquier persona con un poco más de práctica puede crear su propio plugin en base a una plantilla que sen encuentra en el directorio jspsych/plugins/template). Además la comunidad de usuarios de jsPsych está continuamente creando plugins nuevos para agragar nuevas funcionalidades a los experimentos. El límite lo pone la imaginación.

Bueno, volvamos al tutorial…

Paso 5

En base a lo expuesto en el paso anterior, una buena idea es hacer uso de plugins para estructurar nuestro experimento, para ello es necesario importarlos en la parte superior.

<!DOCTYPE html>
<html>
<head>
<title>Mi experimento</title>
<script src="jspsych/jspsych.js"></script>
<script src="jspsych/plugins/jspsych-html-keyboard- response.js"></script>
<link href="jspsych/css/jspsych.css" rel="stylesheet" type="text/css"></link>
</head>
<body></body>
</html>

En este caso haremos uso del plugin html-keyboard-response, el cual nos permitirá mostrar un elemento de HTML en la pantalla (en este caso un texto) y guardar la respuesta que haya sido realizada por medio del teclado.

Una vez que lo tenemos cargado podemos usarlo en nuestro experimento. Lo que tenemos que hacer es declarar un ensayo (trial), en este con nombre trial_hola, que use ese plugin. Para ello definiremos un objeto de JavaScript con la propiedad type igual a html-keyboard-response y a continuación podremos especificar los otros parámetros del plugin en el mismo objeto. A su vez crearemos un array con el nombre timeline_array que incluirá todos los trials de nuestro experimento como si fuera una lista.

<!DOCTYPE html>
<html>
<head>
<title>Mi experimento</title>
<script src="jspsych/jspsych.js"></script>
<script src="jspsych/plugins/jspsych-html-keyboard-response.js"></script>
<link href="jspsych/css/jspsych.css" rel="stylesheet" type="text/css"></link>
</head>
<body></body>
<script>
//Creamos el array que contendra nuestros trials
timeline_array = [];
//Creamos un objeto con nuestro trial
var trial_hola = {
type: 'html-keyboard-response',
stimulus: 'Hola mundo!'
}

</script>
</html>

El parámetro ‘type’ siempre debe estar presente a la hora de crear un objeto para utlizar un plugin. Normalmente este coincide con el nombre del plugin, pero es algo que pueden corroborar en cada caso entrando al archivo correpondiente en el directorio jspsych/plugins y viendo el parámetro ‘name’ del mismo.

En este caso el parámetro extra que definimos (stimulus) corresponde al texto que queremos presentar.

Cosas importante para notar es que los objetos en JavaScript tienen que estar encerrados por llaves {} y sus parámentros separados por comas.

Paso 6

Ahora solo resta decirle a jsPsych que corra un experimento que consiste en este trial que acabamos de crear. Para eso tenemos que hacer varias cosas: Por una lado agregar nuestro trial al array timeline_array por medio del método push, luego vamos a usar la función jsPsych.init especificando el parámetro timelinecon timeline_array como valor.

El timeline es basicamente el lugar donde describimos la estructura de nuestro experimento, es la manera de decirle a jsPsych: “mostrá este trial, luego este y finalmente este otro”. Existen varias maneras diferentes de interactuar con él y podés obtener más información entrando a este enlace.

<!DOCTYPE html>
<html>
<head>
<title>Mi experimento</title>
<script src="jspsych/jspsych.js"></script>
<script src="jspsych/plugins/jspsych-html-keyboard-response.js"></script>
<link href="jspsych/css/jspsych.css" rel="stylesheet" type="text/css"></link>
</head>
<body></body>
<script>
//Creamos el array que contendra nuestros trials
timeline_array = [];

//Creamos un objeto con nuestro trial
var trial_hola = {
type: 'html-keyboard-response',
stimulus: 'Hola mundo!'
}
// Agregamos nuestro trial a timeline_array
timeline_array.push(trial_hola);
// Iniciar el experimento
jsPsych.init({
timeline: timeline_array
})

</script>
</html>

De esto modo obtenemos un experimento que inicia mostrando el texto Hola mundo! y termina luego de presionar una tecla.

¿Esto solo?

Hasta acá ya construimos un experimento básico, pero convengamos que nadie quiere aprender a hacer un experimento que solo te muestra una frase. Lo relevante de lo aprendido hasta acá es que, en base a esta estructura fundamental, agregar funcionalidades es bastante fácil.

A continuación vamos a agregar un trial con el plugin jspsych-cloze el cual permite completar oraciones según el popular paradigma de cloze. Recordemos que siempre que usemos un nuevo plugin necesitamos hacer tres cosas:

  • Importarlo en la parte superior con la siguiente estructura :
<script src="jspsych/plugins/NombreDeNuestroPlugin.js">
  • Crear un objeto para utilizarlo y proporcionarle los parámetros necesarios.
  • Agregarlo al timeline. En este caso usando el método push a a nuestro timeline_array , pero como casi siempre en programación esta no es la única forma de hacerlo.
<!DOCTYPE html>
<html>
<head>
<title>Mi experimento</title>
<script src="jspsych/jspsych.js"></script>
<script src="jspsych/plugins/jspsych-html-keyboard-response.js"></script>
<script src="jspsych/plugins/jspsych-cloze.js"></script>
<link href="jspsych/css/jspsych.css" rel="stylesheet" type="text/css"></link>
</head>
<body></body>
<script>
//Creamos el array que contendra nuestros trials
timeline_array = [];

//Creamos un objeto con nuestro trial saludando
var trial_hola = {
type: 'html-keyboard-response',
stimulus: 'Hola mundo!'
};
//Creamos un objeto con nuestro SEGUNDO trial para la tarea de completar una oración.
var trial_cloze = {
type: 'cloze',
text: 'En casa de %% cuchillo de %%.'
};
// Agregamos nuestros trials a timeline_array
timeline_array.push(trial_hola);
timeline_array.push(trial_cloze);
// Iniciar el experimento
jsPsych.init({
timeline: timeline_array
})

</script>
</html>

Y un trial más con una pregunta y una barra deslizante para responder utilizando otro plugin que viene por defecto llamado html-slider-response

<!DOCTYPE html>
<html>
<head>
<title>Mi experimento</title>
<script src="jspsych/jspsych.js"></script> <script src="jspsych/plugins/jspsych-html-keyboard-response.js"></script>
<script src="jspsych/plugins/jspsych-cloze.js"></script>
<script src="jspsych/plugins/jspsych-html-slider-response.js"></script>
<link href="jspsych/css/jspsych.css" rel="stylesheet" type="text/css"></link>
</head>
<body></body>
<script>
//Creamos el array que contendra nuestros trials
timeline_array = [];

//Creamos un objeto con nuestro PRIMER trial saludando.
var trial_hola = {
type: 'html-keyboard-response',
stimulus: 'Hola mundo!'
}
//Creamos un objeto con nuestro SEGUNDO trial para la tarea de completar una oración.var trial_cloze = {
type: 'cloze',
text: 'En casa de %% cuchillo de %%.'
};
//Creamos un objeto con nuestro TERCER trial para responder mediante una barra deslizante.var slider_trial = {
type: 'html-slider-response',
stimulus: '<p>Te gustó el tutorial?</p>',
labels: ['Para Nada', 'Muchísimo!']
prompt: "<p>Presioná el botón para pasar al siquiente trial</p>",
button_label: "Continuar"
};
// Agregamos nuestros trials a timeline_array
timeline_array.push(trial_hola);
timeline_array.push(trial_cloze);
timeline_array.push(slider_trial);
// Iniciar el experimento
jsPsych.init({
timeline: timeline_array
})

</script>
</html>

Todo muy lindo pero ¿Dónde están los datos?

Algo que preocupa (o debería preocuparle) a cualquier persona que realice experimentos es tener un buen control de los datos generados a partir de ellos. En ese sentido jsPsych posee varias forma de interactuar con ellos. En particular posee una función jsPsych.data.displayData() que muestra en pantalla los resultados del experimento. Para usarla necesitamos llamarla con una callback function (que es un concepto un poco más avanzado, pero no resulta obligatorio indagar demasiado en este momento) llamada on_finish que se ejecutará una vez que termine el experimento. La salida por defecto en la pantalla es en formato .json pero se puede cambiar a .csv si uno lo prefiere.

<!DOCTYPE html>
<html>
<head>
<title>Mi experimento</title>
<script src="jspsych/jspsych.js"></script> <script src="jspsych/plugins/jspsych-html-keyboard-response.js"></script>
<script src="jspsych/plugins/jspsych-html-slider-response.js"></script>
<script src="jspsych/plugins/jspsych-cloze.js"></script>
<link href="jspsych/css/jspsych.css" rel="stylesheet" type="text/css"></link>
</head>
<body></body>
<script>
//Creamos el array que contendra nuestros trials
timeline_array = [];

//Creamos un objeto con nuestro PRIMER trial saludando.
var trial_hola = {
type: 'html-keyboard-response',
stimulus: 'Hola mundo!'
}
//Creamos un objeto con nuestro SEGUNDO trial para la tarea de completar una oración.var trial_cloze = {
type: 'cloze',
text: 'En casa de %% cuchillo de %%.'
};
//Creamos un objeto con nuestro TERCER trial para responder mediante una barra deslizante.var slider_trial = {
type: 'html-slider-response',
stimulus: '<p>Te gustó el tutorial?</p>',
labels: ['Para Nada', 'Muchísimo!'],
prompt: "<p>Presioná el botón para pasar al siquiente trial</p>",
button_label: "Continuar"
};
// Agregamos nuestros trials a timeline_array
timeline_array.push(trial_hola);
timeline_array.push(trial_cloze);
timeline_array.push(slider_trial);
// Iniciar el experimento
jsPsych.init({
timeline: timeline_array,
on_finish: function(){
jsPsych.data.displayData()
}
})</script>
</html>

Con esto ya tendríamos nuestro experimento terminado y luego de realizar las tareas tendríamos que ver la siguiente pantalla:

Podemos observar que nos guarda los tiempos de respuesta o rt , la tecla presionadas (según el código de JavaScript) luego de ‘Hola, mundo!’ que en este caso se trató de la 32, la cual corresponde a la barra espaciadora. También podemos ver la respuesta de la barra deslizante (en mi caso 83/100 😜), el tipo de trial, las palabras escritas en el trial de cloze, etc. La verdad es que es muy cómodo y hace por nosotros un control bastante fino de los datos recolectados.

Ahora les toca jugar a ustedes con esta herramienta.Pueden ver el código completo del experimento que acabamos de crear entrando acá y probar como quedó directamente entrando acá.

La verdad es que queda mucho para contar: por ejemplo como subir el código a la web, como descargar los datos recolectados, como mostrar múltiples trials repetidos, entre muchas otras cosas, pero no quiero que este tutorial se extienda demasiado. Si hay interés seguiré haciendo otros donde explicaré más.

Espero que les sirva y si tienen dudas, sugerencias o críticas serán bien recibidas!

Referencias

--

--

Gustavo Juantorena

PhD student | Cognitive Neuroscience | Buenos Aires, Argentina.