psi.context package

Submodules

psi.context.api module

psi.context.choice module

Introduction

This module contains a collection of generators that facilitate ordering of sequences for an experiment. Each generator takes a sequence and returns a single element on each call. The order of the elements returned depends on the algorithm. A shallow copy of the sequence is created by the generator to prevent side effects if the original sequence is reordered elsewhere. However, if the sequence contains mutable objects, then any modification to the objects will be reflected in the output of the generator.

Examples

Modifying a sequence of immutable objects after passing it to the selector does not affect the output of the selector:

>>> sequence = [1, 3, 8, 9, 12, 0, 4]
>>> choice = exact_order(sequence)
>>> next(choice)
1
>>> sequence[1] = 2
>>> sequence
[1, 2, 8, 9, 12, 0, 4]
>>> next(choice)
3

However, if you have a sequence that contains a mutable object (e.g. a list), then modifications to the mutable object will alter the output of the selector:

>>> sequence = [1, [2, 3], 4, 5, 6]
>>> choice = exact_order(sequence)
>>> next(choice)
1
>>> sequence[1][0] = -5
>>> next(choice)
[-5, 3]

An error is also raised when an empty sequence is passed:

>>> choice = ascending([])
Traceback (most recent call last):
    ...
ValueError: Cannot use an empty sequence

Notes for developers

  • When writing your own generator, use the check_sequence decorator to ensure that the sequence passed is a shallow copy that you can modify in-place without any side effects. This also ensures that if the original sequence is modified by outside code, it will not affect the output of the generator.

  • All generators must be infinite (i.e. they never end) or raise a StopIteration error when the sequence is exhausted.

  • Random sequences have a hard dependency on Numpy (the built-in Python random module is suboptimal for scientific work).

psi.context.choice.ascending(sequence, c=inf, key=None)[source]

Returns elements from the sequence in ascending order. When the last element is reached, loop around to the beginning.

Parameters:
  • sequence ({tuple, list}) – The iterable providing the sequence of values to be produced by the generator.

  • c ({int, np.inf}) – Number of cycles to loop through sequence.

  • key ({None, object}) – Sort key to use when determining ordering of generator. If None, default sort is used. This value is passed to the key parameter of sort.

Example

>>> choice = ascending([1, 3, 8, 9, 12, 0, 4])
>>> next(choice)
0
>>> next(choice)
1
>>> next(choice)
3
psi.context.choice.check_sequence(f)[source]

Used to ensure that the sequence has at least one item and passes a shallow copy of the sequence to the selector so that we don’t have side-effects if the sequence gets modified elsewhere in the program.

psi.context.choice.counterbalanced(sequence, n, c=inf, key=None)[source]

Ensures that each value in sequence is presented an equal number of times over n trials. At the end of the set, will regenerate a new list. If you do not draw from this sequence a number of times that is a multiple of n, then the sequence will not be counterbalanced properly.

When n == 1, this reduces to shuffled_set.

Parameters:
  • sequence ({tuple, list}) – The iterable providing the sequence of values to be produced by the generator.

  • c ({int, np.inf}) – Number of cycles to loop through sequence.

  • key ({None, object}) – Sort key to use when determining ordering of generator. If None, default sort is used. This value is passed to the key parameter of sort.

Example

>>> import numpy as np
>>> choice = counterbalanced([0, 1, 2], 60)
>>> items = [next(choice) for i in range(60)]
>>> np.bincount(items)
array([20, 20, 20])
>>> choice = counterbalanced(['RIGHT', 'LEFT'], 10)
>>> items = [next(choice) for i in range(60)]
>>> sorted(set(items))
['LEFT', 'RIGHT']
>>> items.count('LEFT')
30
>>> items[:10].count('LEFT')
5
>>> items[10:20].count('LEFT')
5
psi.context.choice.descending(sequence, c=inf, key=None)[source]

Returns elements from the sequence in descending order. When the last element is reached, loop around to the beginning.

Parameters:
  • sequence ({tuple, list}) – The iterable providing the sequence of values to be produced by the generator.

  • c ({int, np.inf}) – Number of cycles to loop through sequence.

  • key ({None, object}) – Sort key to use when determining ordering of generator. If None, default sort is used. This value is passed to the key parameter of sort.

Example

>>> choice = descending([1, 3, 8, 9, 12, 0, 4])
>>> next(choice)
12
>>> next(choice)
9
>>> next(choice)
8
psi.context.choice.exact_order(sequence, c=inf, key=None)[source]

Returns elements in the exact order they are provided.

Parameters:
  • sequence ({tuple, list}) – The iterable providing the sequence of values to be produced by the generator.

  • c ({int, np.inf}) – Number of cycles to loop through sequence.

  • key ({None, object}) – Sort key to use when determining ordering of generator. If None, default sort is used. This value is passed to the key parameter of sort.

Example

>>> choice = exact_order([1, 3, 8, 9, 12, 0, 4])
>>> next(choice)
1
>>> next(choice)
3
>>> next(choice)
8
psi.context.choice.format_docstrings()[source]
psi.context.choice.pseudorandom(sequence, c=inf, key=None, seed=None)[source]

Returns a randomly selected element from the sequence.

Parameters:
  • sequence ({tuple, list}) – The iterable providing the sequence of values to be produced by the generator.

  • c ({int, np.inf}) – Number of cycles to loop through sequence.

  • key ({None, object}) – Sort key to use when determining ordering of generator. If None, default sort is used. This value is passed to the key parameter of sort.

  • seed (int) – Seed for random number generator.

psi.context.choice.shuffled_set(sequence, c=inf, key=None, seed=None)[source]

Returns a randomly selected element from the sequence and removes it from the sequence. Once the sequence is exhausted, repopulate list with the original sequence.

This presents an equal number of stim in a single block. When you want to present an equal number of stim over multiple blocks, use counterbalanced.

Parameters:
  • sequence ({tuple, list}) – The iterable providing the sequence of values to be produced by the generator.

  • c ({int, np.inf}) – Number of cycles to loop through sequence.

  • key ({None, object}) – Sort key to use when determining ordering of generator. If None, default sort is used. This value is passed to the key parameter of sort.

  • seed (int) – Seed for random number generator.

psi.context.context_item module

psi.context.expression module

class psi.context.expression.Expr(expression)[source]

Bases: object

evaluate(context)[source]
class psi.context.expression.ExpressionNamespace(expressions=None, globals=None)[source]

Bases: Atom

get_value(name, context=None, force_eval=False)[source]
get_values(names=None, context=None)[source]
reset(context_item_names=None)[source]

Clears the computed values (as well as any user-provided values) in preparation for the next cycle.

set_value(name, value)[source]
set_values(values)[source]
update_expressions(expressions)[source]
update_symbols(symbols)[source]

psi.context.plugin module

psi.context.selector module

psi.context.symbol module

class psi.context.symbol.Function(parent=None, **kwargs)[source]

Bases: Symbol

function

A value which is callable.

get_object()[source]
class psi.context.symbol.ImportedSymbol(parent=None, **kwargs)[source]

Bases: Symbol

get_object()[source]
module

A value of type str.

By default, bytes will NOT be promoted to strings. Pass strict=False to the constructor to enable loose string checking.

class psi.context.symbol.Symbol(parent=None, **kwargs)[source]

Bases: Declarative

Module contents