Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

MRG: Tracker dealer example #310

Merged
merged 12 commits into from
Jun 7, 2017
100 changes: 100 additions & 0 deletions examples/stimuli/tracker_dealer.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
# -*- coding: utf-8 -*-
"""
======================
Tracker Dealer Example
======================

This file shows how to interleave multiple Tracker objects using
:class:`expyfun.stimuli.TrackerDealer`.

In this case, a modeled human subject generates two curves (one for each trial
type: 1 & 2).

@author: maddycapp27
"""

import numpy as np
from expyfun.stimuli import TrackerUD, TrackerDealer
from expyfun.analyze import sigmoid
import matplotlib.pyplot as plt

# define parameters of modeled subject (using sigmoid probability)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FYI if you want you can make pretty sections in the output like this:

https://github.com/mne-tools/mne-python/blob/master/tutorials/plot_artifacts_correction_filtering.py#L49

that render like this:

https://mne-tools.github.io/dev/auto_tutorials/plot_artifacts_correction_filtering.html#removing-power-line-noise-with-notch-filtering

might be overkill in this example but it's something to consider when writing pedagogical examples

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, I'll definitely keep that in mind for the future! For this example, I agree that it's not very necessary though.

true_thresh = [30, 40] # true thresholds for trial types 1 and 2
slope = 0.1
chance = 0.5

##############################################################################
# Defining Tracker Parameters
# ---------------------------
# In this example, the tracker parameters are exactly the same for each
# instance of the up-down adaptive tracker. These are defined such that the
# step sizes vary for both up v. down (the up step size is larger by a factor
# of 3) and based on the number of reversals (the first element in each
# list is the step size until the number of reversals dictacted by the second
# element in change_criteria have occured (i.e. the up step size will be 9
# until 5 reversals have occured, then the up step size will be 3.))
up = 1
down = 1
step_size_up = [9, 3]
step_size_down = [3, 1]
stop_criterion = 30
stop_rule = 'reversals'
start_value = 45
change_criteria = [0, 5]
change_rule = 'reversals'
x_min = 0
x_max = 90


# callback function that prints to console
def callback(event_type, value=None, timestamp=None):
print((str(event_type) + ':').ljust(40) + str(value))


# parameters for the tracker dealer
max_lag = 2
rng_dealer = np.random.RandomState(3) # random seed for selecting trial type

##############################################################################
# Initializing and Running Trackers
# ---------------------------------
# The two trackers in this example use all of the same parameters and then are
# passed into the dealer. After the dealer is created, the type of each trial
# (returned as an index of the array of individual trackers) and trial level
# for that trial can be acquired.

# initialize two tracker objects--one for each trial type
tr_UD = [TrackerUD(callback, up, down, step_size_up, step_size_down,
stop_criterion, stop_rule, start_value,
change_criteria, change_rule, x_min, x_max) for i in [0, 1]]

# initialize TrackerDealer object
tr = TrackerDealer(tr_UD, max_lag, rng_dealer)

# Initialize human state
rng_human = np.random.RandomState(1) # random seed for modeled subject

while not tr.stopped:
# Get information of which trial type is next and what the level is at
# that time from TrackerDealer
ss, level = tr.get_trial()
ss = sum(ss)
tr_UD[ss].respond(rng_human.rand() < sigmoid(level - true_thresh[ss],
lower=chance, slope=slope))

##############################################################################
# Plotting the Results
# ---------------------------
axes = plt.subplots(2, 1)[1]
for i in [0, 1]:
fig, ax, lines = tr[i].plot(ax=axes[i])
lines += tr[i].plot_thresh(4, ax=ax)

lines[0].set_label('Trials')
lines[1].set_label('Reversals')
lines[2].set_label('Estimated threshold')

ax.legend(loc='best')
ax.set_title('Adaptive track of model human trial type {} (true threshold '
'is {})'.format(i + 1, true_thresh[i]))
fig.tight_layout()
2 changes: 1 addition & 1 deletion examples/stimuli/tracker_staircase.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ def callback(event_type, value=None, timestamp=None):
# Do the task until the tracker stops
while not tr.stopped:
tr.respond(rng.rand() < sigmoid(tr.x_current - true_thresh,
lower=0.5, slope=0.1))
lower=chance, slope=slope))

# Plot the results
fig, ax, lines = tr.plot()
Expand Down
2 changes: 1 addition & 1 deletion expyfun/stimuli/_tracker.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ def _check_callback(callback):
class TrackerUD(object):
"""Up-down adaptive tracker

This class implements a standard up-down adative tracker object. Based on
This class implements a standard up-down adaptive tracker object. Based on
how it is configured, it can be used to run a fixed-step m-down n-up
tracker (staircase), or it can implement a weighted up-down procedure.

Expand Down