Experiment#

class psynet.experiment.Experiment(session=None)[source]#

Bases: Experiment

The main experiment class from which to inherit when building experiments.

Several experiment options can be set through the experiment class. For example, the storage back-end can be selected by setting the asset_storage attribute:

class Exp(psynet.experiment.Experiment):
    asset_storage = LocalStorage()

Config variables can be set here, amongst other places (see online documentation for details):

class Exp(psynet.experiment.Experiment):
    config = {
        "min_accumulated_reward_for_abort": 0.15,
        "show_abort_button": True,
    }

Custom CSS stylesheets can be included here, to style the appearance of the experiment:

class Exp(psynet.experiment.Experiment):
    css_links = ["static/theme.css"]

CSS can also be included directly as part of the experiment class via the css attribute, see custom_theme demo for details.

There are a number of variables tied to an experiment all of which are documented below. They have been assigned reasonable default values which can be overridden when defining an experiment (see method _default_variables). Also, they can be enriched with new variables in the following way:

import psynet.experiment

class Exp(psynet.experiment.Experiment):
    variables = {
        "new_variable": "some-value",  # Adding a new variable
    }

These variables can then be changed in the course of experiment, just like (e.g.) participant variables.

from psynet.timeline import CodeBlock

CodeBlock(lambda experiment: experiment.var.set("custom-variable", 42))

Default experiment variables accessible through psynet.experiment.Experiment.var are:

max_participant_paymentfloat

The maximum payment in US dollars a participant is allowed to get. Default: 25.0.

soft_max_experiment_paymentfloat

The recruiting process stops if the amount of accumulated payments (incl. time and performance rewards) in US dollars exceedes this value. Default: 1000.0.

hard_max_experiment_paymentfloat

Guarantees that in an experiment no more is spent than the value assigned. Bonuses are not paid from the point this value is reached and a record of the amount of unpaid bonus is kept in the participant’s unpaid_bonus variable. Default: 1100.0.

big_base_paymentbool

Set this to True if you REALLY want to set base_payment to a value > 20.

There are also a few experiment variables that are set automatically and that should, in general, not be changed manually:

psynet_versionstr

The version of the psynet package.

dallinger_versionstr

The version of the Dallinger package.

python_versionstr

The version of the Python.

hard_max_experiment_payment_email_sentbool

Whether an email to the experimenter has already been sent indicating the hard_max_experiment_payment had been reached. Default: False. Once this is True, no more emails will be sent about this payment limit being reached.

soft_max_experiment_payment_email_sentbool

Whether an email to the experimenter has already been sent indicating the soft_max_experiment_payment had been reached. Default: False. Once this is True, no more emails will be sent about this payment limit being reached.

In addition to the config variables in Dallinger, PsyNet adds the following:

min_browser_versionstr

The minimum version of the Chrome browser a participant needs in order to take a HIT. Default: 80.0.

wage_per_hourfloat

The payment in currency the participant gets per hour. Default: 9.0.

currencystr

The currency in which the participant gets paid. Default: $.

min_accumulated_reward_for_abortfloat

The threshold of reward accumulated in US dollars for the participant to be able to receive compensation when aborting an experiment using the Abort experiment button. Default: 0.20.

show_abort_buttonbool

If True, the Ad page displays an Abort button the participant can click to terminate the HIT, e.g. in case of an error where the participant is unable to finish the experiment. Clicking the button assures the participant is compensated on the basis of the amount of reward that has been accumulated. Default False.

show_rewardbool

If True (default), then the participant’s current estimated reward is displayed at the bottom of the page.

show_footerbool

If True (default), then a footer is displayed at the bottom of the page containing a ‘Help’ button and reward information if show_reward is set to True.

show_progress_barbool

If True (default), then a progress bar is displayed at the top of the page.

check_participant_opened_devtoolsbool

If True, whenever a participant opens the developer tools in the web browser, this is logged as participant.var.opened_devtools = True, and the participant is shown a warning alert message. Default: False. Note: Chrome does not currently expose an official way of checking whether the participant opens the developer tools. People therefore have to rely on hacks to detect it. These hacks can often be broken by updates to Chrome. We’ve therefore disabled this check by default, to reduce the risk of false positives. Experimenters wishing to enable the check for an individual experiment are recommended to verify that the check works appropriately before relying on it. We’d be grateful for any contributions of updated developer tools checks.

window_widthint

Determines the width in pixels of the window that opens when the participant starts the experiment. Only active if recruiter.start_experiment_in_popup_window is True. Default: 1024.

window_heightint

Determines the width in pixels of the window that opens when the participant starts the experiment. Only active if recruiter.start_experiment_in_popup_window is True. Default: 768.

supported_localeslist

List of locales (i.e., ISO language codes) a user can pick from, e.g., '["en"]'. Default: '[]'.

allow_switching_localebool

Allow the user to change the language of the experiment during the experiment. Default: False.

force_google_chromebool

Forces the user to use the Google Chrome browser. If another browser is used, it will give detailed instructions on how to install Google Chrome. Default: True.

force_incognito_modebool

Forces the user to open the experiment in a private browsing (i.e. incognito mode). This is helpful as incognito mode prevents the user from accessing their browsing history, which could be used to influence the experiment. Furthermore it does not enable addons which can interfere with the experiment. If the user is not using incognito mode, it will give detailed instructions on how to open the experiment in incognito mode. Default: False.

allow_mobile_devicesbool

Allows the user to use mobile devices. If it is set to false it will tell the user to open the experiment on their computer. Default: False.

Parameters:

session – The experiment’s connection to the database.

exception HandledError(message=None, participant=None, **kwargs)[source]#

Bases: Exception

exception UniqueIdError(expected, provided, participant)[source]#

Bases: PermissionError

assignment_abandoned(participant)[source]#

What to do if a participant abandons the hit.

This runs when a notification from AWS is received indicating that participant has run out of time. Calls fail_participant().

assignment_reassigned(participant)[source]#

What to do if the assignment assigned to a participant is reassigned to another participant while the first participant is still working.

This runs when a participant is created with the same assignment_id as another participant if the earlier participant still has the status “working”. Calls fail_participant().

assignment_returned(participant)[source]#

What to do if a participant returns the hit.

This runs when a notification from AWS is received indicating that participant has returned the experiment assignment. Calls fail_participant().

bonus(participant)[source]#

Calculates and returns the reward the given participant gets when completing the experiment.

Parameters:

participant (Participant) – The participant.

Returns:

The reward as a float.

check_bonus(reward, participant)[source]#

Ensures that a participant receives no more than a reward of max_participant_payment. Additionally, checks if both soft_max_experiment_payment or max_participant_payment have been reached or exceeded, respectively. Emails are sent out warning the user if either is true.

Parameters:

reward – float The reward calculated in bonus().

Returns:

The possibly reduced reward as a float.

compile_translations_if_necessary(locales_dir, module)[source]#

Compiles translations if necessary.

classmethod config_defaults()[source]#

Override this classmethod to register new default values for config variables. Remember to call super!

classmethod error_page(participant=None, error_text=None, recruiter=None, external_submit_url=None, compensate=True, error_type='default', request_data='', locale='en')[source]#

Render HTML for error page.

classmethod extra_parameters()[source]#

Override this classmethod to register new config variables. It is called during config load. See Extra Configuration for an example.

fail_participant(participant)[source]#

Fail all the nodes of a participant.

classmethod get_participant_from_assignment_id(assignment_id, for_update=False)[source]#

Get a participant with a specified assignment_id. Throws a sqlalchemy.orm.exc.NoResultFound error if there is no such participant, or a sqlalchemy.orm.exc.MultipleResultsFound error if there are multiple such participants.

Parameters:
  • assignment_id (str) – ID of the participant to retrieve.

  • for_update (bool) – Set to True if you plan to update this Participant object. The Participant object will be locked for update in the database and only released at the end of the transaction.

Returns:

  • The corresponding participant object.

classmethod get_participant_from_participant_id(participant_id, for_update=False)[source]#

Get a participant with a specified participant_id. Throws a ValueError if the participant_id is not a valid integer, a sqlalchemy.orm.exc.NoResultFound error if there is no such participant, or a sqlalchemy.orm.exc.MultipleResultsFound error if there are multiple such participants.

Parameters:
  • participant_id (int) – ID of the participant to retrieve.

  • for_update (bool) – Set to True if you plan to update this Participant object. The Participant object will be locked for update in the database and only released at the end of the transaction.

Returns:

  • The corresponding participant object.

classmethod get_participant_from_unique_id(unique_id, for_update=False)[source]#

Get a participant with a specified unique_id. Throws a sqlalchemy.orm.exc.NoResultFound error if there is no such participant, or a sqlalchemy.orm.exc.MultipleResultsFound error if there are multiple such participants.

Parameters:
  • unique_id (str) – Unique ID of the participant to retrieve.

  • for_update (bool) – Set to True if you plan to update this Participant object. The Participant object will be locked for update in the database and only released at the end of the transaction.

Returns:

  • The corresponding participant object.

classmethod get_participant_from_worker_id(worker_id, for_update=False)[source]#

Get a participant with a specified worker_id. Throws a sqlalchemy.orm.exc.NoResultFound error if there is no such participant, or a sqlalchemy.orm.exc.MultipleResultsFound error if there are multiple such participants.

Parameters:
  • worker_id (str) – ID of the participant to retrieve.

  • for_update (bool) – Set to True if you plan to update this Participant object. The Participant object will be locked for update in the database and only released at the end of the transaction.

Returns:

  • The corresponding participant object.

classmethod get_status(lookback='10s')[source]#

Return the status of the experiment as a dictionary.

static google_search_console()[source]#

This route is disabled by default, but can be enabled by setting enable_google_search_console = true in config.txt. Enabling this route allows the site to be claimed in the Google Search Console dashboard of the computational.audition@gmail.com Google account. This allows the account to investigate and debug Chrome warnings (e.g. ‘Deceptive website ahead’). See https://search.google.com/u/4/search-console.

initial_recruitment_size = 1#

int, the number of participants requested when the experiment first starts. Default is 1.

initialize_bot(bot)[source]#

This function is called when a bot is created. It can be used to set stochastic random parameters corresponding to participant latent traits, for example.

e.g.

`bot.var.musician = True

is_complete()[source]#

Method for custom determination of experiment completion. Experiments should override this to provide custom experiment completion logic. Returns None to use the experiment server default logic, otherwise should return True or False.

monitoring_statistics(**kwarg)[source]#

The default data used for the monitoring panels

Parameters:

**kw – arguments passed in from the request

Returns:

An OrderedDict() mapping panel titles to data structures describing the experiment state.

on_launch()[source]#

This function is called upon experiment launch. Unlike the background tasks, this function is blocking: recruitment won’t start until the function has returned.

participant_constructor(*args, **kwargs)[source]#

An ex silico participant.

recruit()[source]#

Recruit participants to the experiment as needed.

This method runs whenever a participant successfully completes the experiment (participants who fail to finish successfully are automatically replaced). By default it recruits 1 participant at a time until all networks are full.

render_exit_message(participant)[source]#

This method is currently only called if the ‘generic’ recruiter is selected. We may propagate it to other recruiter methods eventually too. If left unchanged, the default recruiter exit message from Dallinger will be shown. Otherwise, one can return a custom message in various ways. If you return a string, this will be escaped appropriately and presented as text. Alternatively, more complex HTML structures can be constructed using the Python package dominate, see Examples for details.

Examples

This would be appropriate for experiments with no payment:

tags.div(
    tags.p("Thank you for participating in this experiment!"),
    tags.p("Your responses have been saved. You may close this window."),
)

This kind of structure could be used for passing participants to a particular URL in Prolific:

tags.div(
    tags.p("Thank you for participating in this experiment!"),
    tags.p("Please click the following URL to continue back to Prolific:"),
    tags.a("Finish experiment", href="https://prolific.com"),
)
class psynet.experiment.ExperimentConfig(*args, **kwargs)[source]#

Bases: Base, SQLMixin

This SQL-backed class provides a way to store experiment configuration variables that can change over the course of the experiment. See psynet.experiment.Experiment documentation for example usage.

creation_time = None#

the time at which the Network was created.

details#

a generic column for storing structured JSON data

failed = None#

boolean indicating whether the Network has failed which prompts Dallinger to ignore it unless specified otherwise. Objects are usually failed to indicate something has gone wrong.

failed_reason = None#

an optional reason the object was failed. If the object is failed as part of a cascading failure triggered from another object, the chain of objects will be captured in this field.

id#

a unique number for every entry. 1, 2, 3 and so on…

property1#

a generic column that can be used to store experiment-specific details in String form.

property2#

a generic column that can be used to store experiment-specific details in String form.

property3#

a generic column that can be used to store experiment-specific details in String form.

property4#

a generic column that can be used to store experiment-specific details in String form.

property5#

a generic column that can be used to store experiment-specific details in String form.

time_of_death = None#

the time at which failing occurred

type#
vars#
class psynet.experiment.ExperimentStatus(*args, **kwargs)[source]#

Bases: Base, SQLMixin

creation_time#

the time at which the Network was created.

details#

a generic column for storing structured JSON data

failed#

boolean indicating whether the Network has failed which prompts Dallinger to ignore it unless specified otherwise. Objects are usually failed to indicate something has gone wrong.

failed_reason#

an optional reason the object was failed. If the object is failed as part of a cascading failure triggered from another object, the chain of objects will be captured in this field.

id#

a unique number for every entry. 1, 2, 3 and so on…

property1#

a generic column that can be used to store experiment-specific details in String form.

property2#

a generic column that can be used to store experiment-specific details in String form.

property3#

a generic column that can be used to store experiment-specific details in String form.

property4#

a generic column that can be used to store experiment-specific details in String form.

property5#

a generic column that can be used to store experiment-specific details in String form.

time_of_death#

the time at which failing occurred

to_dict()[source]#

Determines the information that is shown for this object in the dashboard and in the csv files generated by psynet export.

type#
vars#
class psynet.experiment.Request(*args, **kwargs)[source]#

Bases: Base, SQLMixin

creation_time#

the time at which the Network was created.

details#

a generic column for storing structured JSON data

failed = None#

boolean indicating whether the Network has failed which prompts Dallinger to ignore it unless specified otherwise. Objects are usually failed to indicate something has gone wrong.

failed_reason = None#

an optional reason the object was failed. If the object is failed as part of a cascading failure triggered from another object, the chain of objects will be captured in this field.

id#

a unique number for every entry. 1, 2, 3 and so on…

property1#

a generic column that can be used to store experiment-specific details in String form.

property2#

a generic column that can be used to store experiment-specific details in String form.

property3#

a generic column that can be used to store experiment-specific details in String form.

property4#

a generic column that can be used to store experiment-specific details in String form.

property5#

a generic column that can be used to store experiment-specific details in String form.

time_of_death = None#

the time at which failing occurred

to_dict()[source]#

Determines the information that is shown for this object in the dashboard and in the csv files generated by psynet export.

type#
vars = None#
psynet.experiment.get_experiment()[source]#

Returns an initialized instance of the experiment class.

Return type:

Experiment

psynet.experiment.json_serial(obj)[source]#

JSON serializer for objects not serializable by default json code