Trials (1)¶
Source: demos/trial
Often psychological experiments are organized into ‘trials’. A trial is a single unit of data collection, which might typically involve recording the participant’s response to a single stimulus. PsyNet contains some sophisticated abstractions for working with trials in progressively more complex fashions. These are documented in detail elsewhere, but you can get a feel for an approach by looking at the demos.
This simple demo implements an experiment where participants have to give ratings for different
animals. The demo is build around a custom class called RateTrial
, which defines the logic
for a given trial. The key element of this class is the show_trial
method, which
defines the page (or pages) shown to the participant. In the simplest case, this method
just returns a single page, which will most commonly be a Modular Page.
Below this we define the word_ratings
Module. Modules are a useful way for organizing the
logic of PsyNet experiments into discrete components. This Module contains a For Loop,
which here is used to sample three random words to present to the participant.
To present a word in the form of a Rate Trial, we call RateTrial.cue
.
Note
The test_check_bot
method in the Experiment class is used to define a custom function
for checking whether a bot has the expected state. It’s run by the automated PsyNet tests
once a given bot has finished the experiment. For example, the code assert len(trials) == 3
will throw an error if the bot hasn’t completed exactly 3 trials.
import random
from markupsafe import Markup
import psynet.experiment
from psynet.bot import Bot
from psynet.consent import NoConsent
from psynet.modular_page import ModularPage, PushButtonControl
from psynet.page import SuccessfulEndPage
from psynet.timeline import Module, Timeline, for_loop
from psynet.trial.main import Trial
WORDS = [
"cat",
"dog",
"fish",
"monkey",
"giraffe",
"octopus",
]
class RateTrial(Trial):
time_estimate = 3
def show_trial(self, experiment, participant):
word = self.definition["word"]
return ModularPage(
"rate_trial",
Markup(f"How happy is the following word: <strong>{word}</strong>"),
PushButtonControl(
["Not at all", "A little", "Very much"],
),
)
word_ratings = Module(
"word_ratings",
for_loop(
label="Randomly sample three words from the word list",
iterate_over=lambda: random.sample(WORDS, 3),
logic=lambda word: RateTrial.cue(
{
"word": word,
}
),
time_estimate_per_iteration=3,
),
)
class Exp(psynet.experiment.Experiment):
label = "Simple trial demo"
initial_recruitment_size = 1
timeline = Timeline(
NoConsent(),
word_ratings,
SuccessfulEndPage(),
)
test_n_bots = 3
def test_check_bot(self, bot: Bot, **kwargs):
assert not bot.failed
trials = bot.all_trials
assert len(trials) == 3
assert len(set([t.definition["word"] for t in trials])) == 3
assert all([t.definition["word"] in WORDS for t in trials])
assert all([t.complete for t in trials])
assert all([t.finalized for t in trials])