Skip to content

Si vienes de jsPsych: mapa de conceptos y tareas de jsPsych en Potato

Asocia las líneas de tiempo, las condiciones, los plugins y las redirecciones de Prolific de jsPsych con claves de configuración de Potato, y muestra cómo ejecutar una línea de tiempo de jsPsych como una página de un estudio de Potato.

jsPsych es una biblioteca de JavaScript para experimentos conductuales que se ejecutan en un navegador web, y Potato es un servidor para estudios de anotación y de encuesta. La mayoría de los conceptos de jsPsych tienen una clave de configuración en Potato, y desde Potato 2.12.0 un estudio que necesita control a nivel de ensayo puede ejecutar su línea de tiempo de jsPsych como una página de un estudio de Potato.

Un experimento de jsPsych es una línea de tiempo de ensayos. Cada ensayo es un objeto que gestiona un plugin, como html-keyboard-response para un estímulo y una pulsación de tecla, y la línea de tiempo se ejecuta en el navegador del participante. jsPsych no aloja nada, así que un estudio de jsPsych necesita además un servidor que sirva la página y guarde los datos, normalmente JATOS, Pavlovia o Cognition.run. Un estudio de Potato es una secuencia de páginas de fase, como el consentimiento, un cuestionario de selección, las instrucciones, el entrenamiento, la anotación y una explicación final, definidas en una configuración YAML, y Potato es el servidor. En términos de Potato, una línea de tiempo se convierte en phases, terminar el experimento antes de tiempo se convierte en exit_when, y la asignación de condiciones que un estudio de jsPsych obtiene de su alojamiento se convierte en conditions.

Elegir entre jsPsych y Potato

jsPsych encaja con los estudios en los que la temporización de los estímulos y los tiempos de reacción son los datos. Los paradigmas de tiempo de reacción como Stroop, flanker, el test de asociación implícita y la búsqueda visual necesitan controlar qué hay en la pantalla y cuándo, y jsPsych da ese control a un código que se ejecuta en cada ensayo. jsPsych cubre también el seguimiento ocular mediante su extensión WebGazer, el audio con inicios programados y el dibujo personalizado en canvas.

Potato encaja cuando el estudio consiste sobre todo en juicios sobre ítems, como etiquetas, valoraciones, ordenaciones, fragmentos marcados en un texto, comparaciones por pares y cuestionarios. Asigna ítems a los participantes, los entrena y los selecciona, informa de la concordancia entre anotadores (fiabilidad entre evaluadores) y gestiona la llegada desde Prolific o un grupo de participantes de SONA y el retorno a ellos. Las páginas que rodean una tarea, como el consentimiento, los cuestionarios de selección, las instrucciones, la práctica con retroalimentación y una encuesta posterior al estudio, son entradas de la configuración y no código.

Un estudio necesita ambos cuando combina una tarea cronometrada con valoraciones o encuestas, por ejemplo un bloque de Stroop seguido de valoraciones de la valencia de palabras. Pon la línea de tiempo de jsPsych en una página type: jspsych y deja que Potato ejecute el resto. Los datos de los ensayos se guardan por participante junto a las valoraciones, y el participante recibe un único código de finalización al final.

Mapa de conceptos de jsPsych a Potato

La tabla empareja cada concepto de jsPsych con la clave de Potato que hace el mismo trabajo. La mayoría de las filas son una clave de configuración, y las notas indican dónde la correspondencia es parcial.

jsPsychPotatoNotas
Línea de tiempophases.orderVarias páginas por tipo de fase
EnsayoUna página de fase, o un ítem de anotaciónLos ítems proceden de data_files, no de la configuración
Variables de la línea de tiempoCampos del archivo de datosinstance_display elige qué campos ve el participante
conditional_functionshow_when de una páginaLa misma gramática de reglas que display_logic a nivel de pregunta
Pregunta condicionaldisplay_logicConsulta Flujos de trabajo multifase
jsPsych.abortExperiment()exit_when de una páginaMuestra un mensaje, o devuelve el resultado de exclusión de la plataforma
loop_functiontraining.failure_action: repeat_trainingSolo se repite la fase de entrenamiento
randomize_order, sampleassignment_strategy: random, randomize_questionsEl orden de los ítems usa una semilla por participante
Opciones de respuesta barajadasrandomize_order en un esquemaEl randomize_order de Potato baraja las opciones de un esquema, y el orden mostrado queda registrado
Asignación entre sujetos, desde el alojamiento (p. ej., una sesión de lote de JATOS)conditionsAsignación equilibrada, aleatoria o rotatoria de participantes a celdas
Orden de bloques contrabalanceadophases.counterbalance con method: latin_squareCuadrados latinos balanceados (de Williams)
survey-likert, survey-multi-choice, survey-multi-select, survey-textlikert, radio, multiselect, textMás 55 instrumentos publicados por su nombre
html-slider-responseslider, vas
maxdiffbwsEscalamiento best-worst, con puntuación
free-sortcard_sortClasificación de tarjetas, cerrada o abierta
clozeclozeLa clave de respuestas se queda en el servidor
same-different-htmlpairwiseSin presentación secuencial cronometrada
html-keyboard-response con trial_durationtrial_timingFijación, duración del estímulo, plazo, tiempo de reacción con teclas asociadas a etiquetas
instructions, external-htmlPáginas de instrucciones, archivos HTML
Datos de interacción (pérdida de foco, foco)authenticitySalidas de la página, copias, pegados desde fuera
Extensión de seguimiento del ratónextensions: [mouse-tracking] en una página de jsPsychMuestras x/y por ensayo. En los propios ítems de Potato, authenticity.track_pointer conserva solo totales del puntero
Lectura autoadministrada y maze de jspsych-contribtrial_timing.presentationLectura autoadministrada y maze, con tiempos de lectura por región
Valoraciones de calidad de audio, comprobaciones de auricularesEsquema listening_test, página type: headphone_checkPruebas de escucha y la comprobación de auriculares, puntuadas en el servidor
(sin plugin)keystroke_loggingTemporización de pulsaciones en campos de texto libre, sin los caracteres
Parámetros de URL de Prolific, redirección de finalizaciónlogin.type: url_direct y completion_code, o crowdsourcing.provider: prolificConsulta Cómo realizar un estudio de crowdsourcing
SONAcrowdsourcing.provider: sonaCréditos concedidos desde el servidor
jsPsych.data.get().csv()python -m potato.export60 formatos, entre ellos CSV, JSONL, Parquet, Psych-DS y un Frictionless Data Package
JATOS, Pavlovia, Cognition.runEl propio PotatoEjecútalo en tu propio servidor o en un Space de Hugging Face
Modo de simulaciónpython -m potato.simulatorParticipantes simulados contra un servidor en marcha

Paradigmas que necesitan una línea de tiempo de jsPsych

Algunos paradigmas necesitan código de ensayo propio, y las páginas de ítems de Potato no lo ejecutan. Mantenlos en una línea de tiempo de jsPsych:

  • Presentación sincronizada con los fotogramas. Estímulos dibujados en un canvas, máscaras sincronizadas con un fotograma y audio programado con la Web Audio API.
  • Trayectorias del ratón. El bloque authenticity de Potato cuenta los movimientos y la distancia del puntero por ítem y no conserva posiciones. Una página de jsPsych con extensions: [mouse-tracking] registra muestras x/y en cada ensayo que activa la extensión.
  • Pantalla completa entre ensayos. Cada ítem de Potato es una carga de página, y los navegadores salen de la pantalla completa cuando cambia la página. Una página de jsPsych mantiene la pantalla completa durante toda su línea de tiempo.
  • Bucles y ramificaciones dentro de un bloque de ensayos. Potato ramifica por página (show_when), por pregunta (display_logic) y por intento de entrenamiento, así que un bloque que se ramifica según la respuesta anterior corresponde a jsPsych.

Los propios ítems de Potato también pueden ejecutar juicios rápidos. trial_timing convierte cada ítem de anotación en un ensayo cronometrado con una cruz de fijación, una duración del estímulo, un plazo de respuesta y teclas asociadas a etiquetas, y mide el tiempo de reacción en el navegador desde el fotograma en el que apareció el estímulo. trial_timing encaja con la decisión léxica o los juicios rápidos de gramaticalidad sobre una lista de ítems. El inicio se conoce con precisión de un fotograma (unos 17 ms a 60 Hz).

El seguimiento ocular y la grabación por webcam quedan fuera de ambos tipos de página. Potato no incluye la extensión WebGazer de jsPsych ni sus plugins de calibración, porque WebGazer necesita 'unsafe-eval' y la Content-Security-Policy de la página de jsPsych no lo permite. Un estudio de seguimiento ocular se ejecuta en un alojamiento de jsPsych como JATOS o Pavlovia, o en Gorilla.

Un estudio de Potato con una tarea de jsPsych

La configuración siguiente es el núcleo del ejemplo de Stroop que se incluye con Potato. A los participantes se les asigna una de dos condiciones de retroalimentación, responden a un cuestionario de selección que termina el estudio para quien declare dificultades para distinguir colores, hacen una tarea de Stroop en jsPsych, valoran palabras y terminan con una encuesta de explicación final cuyas preguntas aparecen en un orden aleatorio para cada participante, con el cuadro de comentarios al final. El bloque es parcial. La versión completa, con el archivo de datos, los archivos de encuesta y la línea de tiempo, está en examples/advanced/jspsych-stroop/.

yaml
conditions:
  factors:
    feedback: [none, immediate]
  assignment: balanced          # each arrival goes to the cell with the fewest participants
 
phases:
  order: [screener, stroop, annotation, debrief]
  screener:
    type: prestudy
    file: surveys/screener.json
    exit_when:
      show_when:
        - {schema: colour_vision, operator: equals, value: "Yes"}
      message: This study needs you to tell red, green and blue apart quickly, so we cannot include you.
  stroop:
    type: jspsych
    timeline: tasks/stroop.js
    plugins: [instructions, html-keyboard-response]
  debrief:
    type: poststudy
    file: surveys/debrief.json
    randomize_questions:
      pin_last: [comments]      # the open comment box stays last

La asignación equilibrada mantiene las dos condiciones de retroalimentación a una persona de distancia como máximo a medida que llegan los participantes. Añadir balance_on: completed hace que solo los participantes que terminan sin ser excluidos cuenten para una condición, de modo que un abandono lo reemplaza la siguiente persona que llega.

El archivo de la línea de tiempo asigna una función a window.potatoTimeline. Potato crea la instancia de jsPsych, llama a la función con ella y con un objeto potato, y guarda los datos cuando termina la línea de tiempo. La función devuelve los ensayos, y puede leer la condición del participante para decidir cuáles incluir:

javascript
window.potatoTimeline = function (jsPsych, potato) {
    var trial = {
        type: jsPsychHtmlKeyboardResponse,
        stimulus: '<p style="font-size:48px;color:#c62828">GREEN</p>',
        choices: ['r', 'g', 'b']
    };
    var feedback = {
        type: jsPsychHtmlKeyboardResponse,
        stimulus: '<p>Correct key: R</p>',
        trial_duration: 800
    };
    return potato.conditions.feedback === 'immediate' ? [trial, feedback] : [trial];
};

La línea de tiempo no llama a initJsPsych ni define un on_finish a nivel de experimento, porque Potato hace ambas cosas. El on_finish a nivel de ensayo y el resto de la API de jsPsych funcionan como siempre. potato.participant contiene el ID de Prolific o de SONA, potato.asset(path) devuelve la URL de un estímulo del assets_dir de la página, y expose_answers pasa respuestas de páginas de encuesta anteriores a potato.answers.

Potato incluye jsPsych 8.3.0 y 15 de sus plugins, entre ellos los de teclado, botón, control deslizante, audio, vídeo y encuesta, preload y fullscreen. Un estudio que use solo estos plugins no carga nada desde una CDN, así que funciona en un servidor sin acceso a internet. Los demás plugins, incluidos los de jspsych-contrib, se cargan mediante extra_scripts como compilaciones para navegador. Arranca el ejemplo desde la raíz del repositorio de Potato:

bash
python potato/flask_server.py start examples/advanced/jspsych-stroop/config.yaml -p 8000

Datos de los ensayos y exportación desde una página de jsPsych

Cada ejecución de la línea de tiempo se guarda en la base de datos del proyecto (tabla runtime_runs) con el participante, la página, el número de intento y las condiciones del participante, y cada fila de ensayo recibe potato_user, potato_run_id, potato_attempt y una columna condition_<factor> por cada factor. El formato de exportación jspsych escribe un CSV de ejecuciones, un CSV de ensayos con todas las columnas que registró jsPsych, los eventos de pérdida de foco y de pantalla completa de jsPsych y el JSON sin procesar de cada ejecución:

bash
python -m potato.export --config config.yaml --format jspsych --output ./export/

Con save: incremental, cada ensayo se guarda en cuanto termina, y un participante que cierra la pestaña deja igualmente los ensayos que completó. Una recarga reinicia la línea de tiempo desde el principio, porque jsPsych no puede reanudar una línea de tiempo a medias. Una ejecución que ya había enviado datos queda registrada como incompleta, y la ejecución siguiente lleva un potato_attempt mayor, de modo que un análisis puede excluir los segundos intentos o conservarlos.

La exportación CSV del mismo estudio escribe participants.csv, una fila por participante con su condición, los órdenes de las páginas, las páginas saltadas y cualquier exclusión. Potato lo llama el registro del flujo, y se une con los datos de los ensayos mediante el ID del participante. Las ejecuciones de jsPsych se guardan en el project.sqlite del directorio de la tarea sea cual sea el backend de almacenamiento que use el servidor.

En la página rige la temporización propia de jsPsych, porque Potato no ejecuta nada más ahí. La documentación sobre la precisión de la temporización de jsPsych indica que los tiempos de reacción medidos en JavaScript son entre 10 y 40 ms más largos que en el software de laboratorio estándar, con una varianza similar. Compara los tiempos de reacción dentro de cada participante, o modélalos con un término de participante, ya que los teclados y las pantallas añaden una latencia que varía de un equipo a otro.

Lecturas adicionales