Source code for neurogym.envs.antireach

"""Anti-reach or anti-saccade task."""

import numpy as np

import neurogym as ngym
from neurogym import spaces


[docs] class AntiReach(ngym.TrialEnv): """Anti-response task. During the fixation period, the agent fixates on a fixation point. During the following stimulus period, the agent is then shown a stimulus away from the fixation point. Finally, the agent needs to respond in the opposite direction of the stimulus during the decision period. Args: anti: bool, if True, requires an anti-response. If False, requires a pro-response, i.e. response towards the stimulus. """ metadata = { 'paper_link': 'https://www.nature.com/articles/nrn1345', 'paper_name': """Look away: the anti-saccade task and the voluntary control of eye movement""", 'tags': ['perceptual', 'steps action space'] } def __init__(self, dt=100, anti=True, rewards=None, timing=None, dim_ring=32): super().__init__(dt=dt) self.anti = anti # Rewards self.rewards = {'abort': -0.1, 'correct': +1., 'fail': 0.} if rewards: self.rewards.update(rewards) self.timing = { 'fixation': 500, 'stimulus': 500, 'delay': 0, 'decision': 500} if timing: self.timing.update(timing) self.abort = False # action and observation spaces self.dim_ring = dim_ring self.theta = np.arange(0, 2 * np.pi, 2 * np.pi / dim_ring) self.choices = np.arange(dim_ring) name = {'fixation': 0, 'stimulus': range(1, dim_ring + 1)} self.observation_space = spaces.Box( -np.inf, np.inf, shape=(1+dim_ring,), dtype=np.float32, name=name) name = {'fixation': 0, 'choice': range(1, dim_ring + 1)} self.action_space = spaces.Discrete(1+dim_ring, name=name) def _new_trial(self, **kwargs): # Trial info trial = { 'ground_truth': self.rng.choice(self.choices), 'anti': self.anti, } trial.update(kwargs) ground_truth = trial['ground_truth'] if trial['anti']: stim_theta = np.mod(self.theta[ground_truth] + np.pi, 2*np.pi) else: stim_theta = self.theta[ground_truth] # Periods periods = ['fixation', 'stimulus', 'delay', 'decision'] self.add_period(periods) self.add_ob(1, period=['fixation', 'stimulus', 'delay'], where='fixation') stim = np.cos(self.theta - stim_theta) self.add_ob(stim, 'stimulus', where='stimulus') self.set_groundtruth(ground_truth, period='decision', where='choice') return trial def _step(self, action): new_trial = False # rewards reward = 0 gt = self.gt_now # observations if self.in_period('fixation'): if action != 0: # action = 0 means fixating new_trial = self.abort reward += self.rewards['abort'] elif self.in_period('decision'): if action != 0: new_trial = True if action == gt: reward += self.rewards['correct'] self.performance = 1 else: reward += self.rewards['fail'] return self.ob_now, reward, False, {'new_trial': new_trial, 'gt': gt}