Skip to content

Umstieg von jsPsych: Begriffszuordnung und jsPsych-Aufgaben in Potato

Ordnet jsPsych-Timelines, Bedingungen, Plugins und Prolific-Weiterleitungen Potato-Konfigurationsschlüsseln zu und zeigt, wie eine jsPsych-Timeline als eine Seite einer Potato-Studie läuft.

jsPsych ist eine JavaScript-Bibliothek für Verhaltensexperimente, die im Webbrowser laufen, und Potato ist ein Server für Annotations- und Umfragestudien. Für die meisten jsPsych-Konzepte gibt es einen Potato-Konfigurationsschlüssel, und seit Potato 2.12.0 kann eine Studie, die Kontrolle auf Trial-Ebene braucht, ihre jsPsych-Timeline als eine Seite einer Potato-Studie ausführen.

Ein jsPsych-Experiment ist eine Timeline aus Trials. Jeder Trial ist ein Objekt, das ein Plugin verarbeitet, etwa html-keyboard-response für einen Stimulus und einen Tastendruck, und die Timeline läuft im Browser der teilnehmenden Person. jsPsych hostet nichts, daher braucht eine jsPsych-Studie zusätzlich einen Server, der die Seite ausliefert und die Daten speichert, häufig JATOS, Pavlovia oder Cognition.run. Eine Potato-Studie ist eine Folge von Phasenseiten, etwa Einwilligung, ein Screener, Anweisungen, Training, Annotation und ein Debriefing, definiert in einer YAML-Konfiguration, und Potato ist der Server. In Potato-Begriffen wird eine Timeline zu phases, das vorzeitige Beenden des Experiments zu exit_when, und die Bedingungszuweisung, die eine jsPsych-Studie von ihrem Host erhält, zu conditions.

Zwischen jsPsych und Potato wählen

jsPsych passt zu Studien, in denen Stimulus-Timing und Reaktionszeiten die Daten sind. Reaktionszeitparadigmen wie Stroop, Flanker, der implizite Assoziationstest und visuelle Suche brauchen Kontrolle darüber, was wann auf dem Bildschirm ist, und jsPsych gibt diese Kontrolle an Code weiter, der bei jedem Trial läuft. jsPsych deckt außerdem Eye-Tracking über seine Erweiterung WebGazer, Audio mit geplanten Onsets und eigenes Zeichnen auf einem Canvas ab.

Potato passt, wenn die Studie überwiegend aus Urteilen über Items besteht, etwa Labels, Bewertungen, Rangfolgen, im Text markierte Spans, paarweise Vergleiche und Fragebögen. Es weist Teilnehmenden Items zu, trainiert und screent sie, berichtet die Inter-Annotator-Übereinstimmung (Interrater-Reliabilität) und übernimmt die Ankunft von und die Rückkehr zu Prolific oder einem SONA-Teilnehmerpool. Die Seiten rund um eine Aufgabe, etwa Einwilligung, Screener, Anweisungen, Übung mit Feedback und eine Abschlussbefragung, sind Konfigurationseinträge statt Code.

Eine Studie braucht beides, wenn sie eine zeitgesteuerte Aufgabe mit Bewertungen oder Umfragen kombiniert, zum Beispiel einen Stroop-Block, gefolgt von Valenzbewertungen von Wörtern. Legen Sie die jsPsych-Timeline auf eine Seite mit type: jspsych und lassen Sie Potato den Rest ausführen. Die Trial-Daten werden pro teilnehmender Person neben den Bewertungen gespeichert, und die Person erhält am Ende einen einzigen Abschlusscode.

Begriffszuordnung von jsPsych zu Potato

Die Tabelle stellt jedem jsPsych-Konzept den Potato-Schlüssel gegenüber, der dieselbe Aufgabe erfüllt. Die meisten Zeilen sind ein Konfigurationsschlüssel, und die Anmerkungen sagen, wo die Entsprechung nur teilweise gilt.

jsPsychPotatoAnmerkungen
Timelinephases.orderMehrere Seiten pro Phasentyp
TrialEine Phasenseite oder ein AnnotationsitemItems stammen aus data_files, nicht aus der Konfiguration
Timeline-VariablenFelder in der Datendateiinstance_display wählt, welche Felder die teilnehmende Person sieht
conditional_functionshow_when einer SeiteDieselbe Regelgrammatik wie display_logic auf Fragenebene
Bedingte Fragedisplay_logicSiehe Mehrphasige Workflows
jsPsych.abortExperiment()exit_when einer SeiteZeigt eine Nachricht an oder gibt das Screen-out-Ergebnis der Plattform zurück
loop_functiontraining.failure_action: repeat_trainingNur die Trainingsphase wird wiederholt
randomize_order, sampleassignment_strategy: random, randomize_questionsDie Item-Reihenfolge wird pro teilnehmender Person geseedet
Gemischte Antwortoptionenrandomize_order an einem SchemaPotatos randomize_order mischt die Optionen eines Schemas, und die angezeigte Reihenfolge wird aufgezeichnet
Between-Subjects-Zuweisung durch den Host (z. B. eine JATOS-Batch-Sitzung)conditionsAusgewogene, zufällige oder reihum erfolgende Zuweisung von Teilnehmenden zu Zellen
Ausbalancierte Blockreihenfolgephases.counterbalance mit method: latin_squareBalancierte lateinische Quadrate (Williams)
survey-likert, survey-multi-choice, survey-multi-select, survey-textlikert, radio, multiselect, textDazu 55 veröffentlichte Instrumente, per Name abrufbar
html-slider-responseslider, vas
maxdiffbwsBest-Worst-Scaling, mit Auswertung
free-sortcard_sortCard Sorting, geschlossen oder offen
clozeclozeDer Lösungsschlüssel bleibt auf dem Server
same-different-htmlpairwiseKeine zeitgesteuerte sequenzielle Darbietung
html-keyboard-response mit trial_durationtrial_timingFixation, Stimulusdauer, Deadline, Reaktionszeit von Taste zu Label
instructions, external-htmlAnweisungsseiten, HTML-Dateien
Interaktionsdaten (Blur, Focus)authenticityVerlassen der Seite, Kopiervorgänge, Einfügen von außen
Mouse-Tracking-Erweiterungextensions: [mouse-tracking] auf einer jsPsych-Seitex/y-Messpunkte pro Trial. Auf Potatos eigenen Items speichert authenticity.track_pointer nur Summen der Zeigerbewegungen
Self-Paced Reading und Maze aus jspsych-contribtrial_timing.presentationSelf-Paced Reading und Maze, mit Lesezeiten pro Region
Bewertungen der Audioqualität, KopfhörertestsSchema listening_test, Seite mit type: headphone_checkHörtests und der Kopfhörertest, auf dem Server ausgewertet
(kein Plugin)keystroke_loggingTastenanschlag-Timing in Freitextfeldern, ohne die Zeichen
Prolific-URL-Parameter, Abschlussweiterleitunglogin.type: url_direct und completion_code, oder crowdsourcing.provider: prolificSiehe Eine Crowdsourcing-Studie durchführen
SONAcrowdsourcing.provider: sonaStudienpunkte werden vom Server vergeben
jsPsych.data.get().csv()python -m potato.export60 Formate, darunter CSV, JSONL, Parquet, Psych-DS und ein Frictionless Data Package
JATOS, Pavlovia, Cognition.runPotato selbstAuf dem eigenen Server oder in einem Hugging Face Space betreiben
Simulationsmoduspython -m potato.simulatorSimulierte Teilnehmende gegen einen laufenden Server

Paradigmen, die eine jsPsych-Timeline brauchen

Manche Paradigmen brauchen eigenen Trial-Code, und Potatos Item-Seiten führen ihn nicht aus. Behalten Sie diese in einer jsPsych-Timeline:

  • Frame-genaue Darbietung. Auf einem Canvas gezeichnete Stimuli, auf den Frame getimte Masken und mit der Web Audio API geplante Audiowiedergabe.
  • Mausbahnen. Potatos Block authenticity zählt Zeigerbewegungen und Distanz pro Item und speichert keine Positionen. Eine jsPsych-Seite mit extensions: [mouse-tracking] zeichnet x/y-Messpunkte bei jedem Trial auf, der die Erweiterung einschaltet.
  • Vollbildmodus über Trials hinweg. Jedes Potato-Item ist ein Seitenaufruf, und Browser verlassen den Vollbildmodus, wenn die Seite wechselt. Eine jsPsych-Seite hält den Vollbildmodus für ihre gesamte Timeline.
  • Schleifen und Verzweigungen innerhalb eines Trial-Blocks. Potato verzweigt pro Seite (show_when), pro Frage (display_logic) und pro Trainingsversuch. Ein Block, der anhand der vorherigen Antwort verzweigt, gehört daher in jsPsych.

Potatos eigene Items können ebenfalls schnelle Urteile ausführen. trial_timing macht jedes Annotationsitem zu einem zeitgesteuerten Trial mit Fixationskreuz, Stimulusdauer, Antwortdeadline und auf Labels abgebildeten Tasten und misst die Reaktionszeit im Browser ab dem Frame, in dem der Stimulus erschienen ist. trial_timing eignet sich für lexikalische Entscheidungen oder schnelle Grammatikalitätsurteile über eine Liste von Items. Der Onset ist auf den Frame genau bekannt (etwa 17 ms bei 60 Hz).

Eye-Tracking und Webcam-Aufzeichnung liegen außerhalb beider Seitenarten. Potato liefert jsPsychs Erweiterung WebGazer und deren Kalibrierungs-Plugins nicht mit, weil WebGazer 'unsafe-eval' benötigt und die Content-Security-Policy der jsPsych-Seite das nicht erlaubt. Eine Eye-Tracking-Studie läuft auf einem jsPsych-Host wie JATOS oder Pavlovia oder in Gorilla.

Eine Potato-Studie mit einer jsPsych-Aufgabe

Die folgende Konfiguration ist der Kern des Stroop-Beispiels, das mit Potato ausgeliefert wird. Teilnehmende werden einer von zwei Feedback-Bedingungen zugewiesen, beantworten einen Screener, der die Studie für alle beendet, die Schwierigkeiten beim Unterscheiden von Farben angeben, bearbeiten eine Stroop-Aufgabe in jsPsych, bewerten Wörter und schließen mit einer Debriefing-Umfrage ab, deren Fragen für jede teilnehmende Person in zufälliger Reihenfolge erscheinen, mit dem Kommentarfeld zuletzt. Der Block ist unvollständig. Die vollständige Version mit Datendatei, Umfragedateien und Timeline liegt in 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

Die ausgewogene Zuweisung hält die beiden Feedback-Bedingungen beim Eintreffen der Teilnehmenden auf höchstens eine Person Unterschied. Mit balance_on: completed zählen nur Teilnehmende, die ohne Screen-out fertig werden, zu einer Bedingung, sodass ein Abbruch durch die nächste eintreffende Person ersetzt wird.

Die Timeline-Datei weist window.potatoTimeline eine Funktion zu. Potato erzeugt die jsPsych-Instanz, ruft die Funktion mit ihr und einem potato-Objekt auf und speichert die Daten, wenn die Timeline endet. Die Funktion gibt die Trials zurück und kann die Bedingung der teilnehmenden Person lesen, um zu entscheiden, welche sie aufnimmt:

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];
};

Die Timeline ruft weder initJsPsych auf noch setzt sie ein on_finish auf Experimentebene, denn beides übernimmt Potato. on_finish auf Trial-Ebene und der Rest der jsPsych-API funktionieren wie gewohnt. potato.participant enthält die Prolific- oder SONA-ID, potato.asset(path) gibt die URL eines Stimulus im assets_dir der Seite zurück, und expose_answers übergibt Antworten von früheren Umfrageseiten an potato.answers.

Potato liefert jsPsych 8.3.0 und 15 seiner Plugins mit, darunter die Plugins für Tastatur, Schaltflächen, Schieberegler, Audio, Video, Umfragen, preload und fullscreen. Eine Studie, die nur diese Plugins verwendet, lädt nichts von einem CDN und läuft daher auf einem Server ohne Internetzugang. Andere Plugins, auch solche aus jspsych-contrib, werden als Browser-Builds über extra_scripts geladen. Starten Sie das Beispiel aus dem Wurzelverzeichnis des Potato-Repositorys:

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

Trial-Daten und Export von einer jsPsych-Seite

Jeder Lauf der Timeline wird in der Projektdatenbank (Tabelle runtime_runs) gespeichert, mit der teilnehmenden Person, der Seite, der Versuchsnummer und den Bedingungen der Person, und jede Trial-Zeile erhält potato_user, potato_run_id, potato_attempt und eine Spalte condition_<factor> pro Faktor. Das Exportformat jspsych schreibt eine CSV-Datei der Läufe, eine CSV-Datei der Trials mit jeder Spalte, die jsPsych aufgezeichnet hat, jsPsychs Blur- und Vollbild-Ereignisse sowie das rohe JSON jedes Laufs:

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

Mit save: incremental wird jeder Trial gespeichert, sobald er abgeschlossen ist, und eine teilnehmende Person, die den Tab schließt, hinterlässt dennoch die bereits bearbeiteten Trials. Ein Neuladen startet die Timeline von vorn, weil jsPsych eine Timeline nicht mittendrin fortsetzen kann. Ein Lauf, der bereits Daten gesendet hatte, bleibt als unvollständig erhalten, und der nächste Lauf trägt ein höheres potato_attempt, sodass eine Analyse zweite Versuche ausschließen oder behalten kann.

Der CSV-Export derselben Studie schreibt participants.csv, eine Zeile pro teilnehmender Person mit ihrer Bedingung, Seitenreihenfolgen, übersprungenen Seiten und einem etwaigen Screen-out. Potato nennt dies den Ablaufdatensatz, und er lässt sich über die ID der teilnehmenden Person mit den Trial-Daten verknüpfen. jsPsych-Läufe werden in project.sqlite im Aufgabenverzeichnis gespeichert, unabhängig davon, welches Speicher-Backend der Server verwendet.

Auf der Seite gilt jsPsychs eigenes Timing, weil Potato dort nichts anderes ausführt. Die Dokumentation zur Timing-Genauigkeit von jsPsych gibt an, dass in JavaScript gemessene Reaktionszeiten 10-40 ms länger ausfallen als in üblicher Laborsoftware, bei ähnlicher Varianz. Vergleichen Sie Reaktionszeiten innerhalb von Teilnehmenden, oder modellieren Sie sie mit einem Term für die teilnehmende Person, da Tastaturen und Bildschirme eine Latenz hinzufügen, die sich zwischen Rechnern unterscheidet.

Weiterführende Informationen