def stimulus_main(self): ## 1. present cue if 'cue' in self.this_trial.annotations: cue = self.this_trial.annotations["cue"] self.log.debug("cue light turning on") cue_start = dt.datetime.now() if cue=="red": self.panel.cue.red() elif cue=="green": self.panel.cue.green() elif cue=="blue": self.panel.cue.blue() utils.wait(self.parameters["cue_duration"]) self.panel.cue.off() cue_dur = (dt.datetime.now() - cue_start).total_seconds() cue_time = (cue_start - self.this_trial.time).total_seconds() cue_event = utils.Event(time=cue_time, duration=cue_dur, label='cue', name=cue, ) self.this_trial.events.append(cue_event) utils.wait(self.parameters["cuetostim_wait"]) ## 2. play stimulus stim_start = dt.datetime.now() self.this_trial.stimulus_event.time = (stim_start - self.this_trial.time).total_seconds() self.panel.speaker.play() # already queued in stimulus_pre()
def trial_post(self): '''things to do at the end of a trial''' self.this_trial.duration = (dt.datetime.now() - self.this_trial.time).total_seconds() self.analyze_trial() self.save_trial(self.this_trial) self.write_summary() utils.wait(self.parameters['intertrial_min']) # determine if next trial should be a correction trial self.do_correction = True if len(self.trials) > 0: if self.parameters['correction_trials']: if self.this_trial.correct == True: self.do_correction = False elif self.this_trial.response == 'none': if self.this_trial.type_ == 'normal': self.do_correction = self.parameters[ 'no_response_correction_trials'] else: self.do_correction = False else: self.do_correction = False if self.check_session_schedule() == False: raise EndSession
def flash(self, dur=1.0, isi=0.1): """ Flashes the LED on and off with *isi* seconds high and low for *dur* seconds, then revert LED to prior state. Parameters ---------- dur : float, optional Duration of the light flash in seconds. isi : float,optional Time interval between toggles. (0.5 * period) Returns ------- (datetime, float) Timestamp of the flash and the flash duration """ LED_state = self.LED.read() flash_time = datetime.datetime.now() flash_duration = datetime.datetime.now() - flash_time while flash_duration < datetime.timedelta(seconds=dur): self.LED.toggle() utils.wait(isi) flash_duration = datetime.datetime.now() - flash_time self.LED.write(LED_state) return (flash_time, flash_duration)
def response_main(self): response_start = dt.datetime.now() while True: elapsed_time = (dt.datetime.now() - self.this_trial.time).total_seconds() response_time = elapsed_time - self.this_trial.stimulus_event.time if response_time > self.this_trial.annotations['max_wait']: self.panel.speaker.stop() self.this_trial.response = 'none' self.log.info('no response') return for class_, port in self.class_assoc.items(): if port.status(): self.this_trial.rt = (dt.datetime.now() - response_start).total_seconds() self.panel.speaker.stop() self.this_trial.response = class_ self.summary['responses'] += 1 response_event = utils.Event( name=self.parameters['classes'][class_]['component'], label='peck', time=elapsed_time, ) self.this_trial.events.append(response_event) self.log.info('response: %s' % (self.this_trial.response)) return utils.wait(.015)
def temp(): if t_min == t_max: t = t_max else: t = random.randrange(t_min, t_max) utils.wait(t) return next_state
def feed(self, dur=2.0, error_check=True): """ Performs a feed Parameters ---------- dur : float, optional duration of feed in seconds Returns ------- (datetime, float) Timestamp of the feed and the feed duration Raises ------ HopperAlreadyUpError The Hopper was already up at the beginning of the feed. HopperWontComeUpError The Hopper did not raise for the feed. HopperWontDropError The Hopper did not drop fater the feed. """ assert self.max_lag < dur, "max_lag (%ss) must be shorter than duration (%ss)" % (self.max_lag, dur) try: self.check() except HopperActiveError as e: self.solenoid.write(False) raise HopperAlreadyUpError(e) feed_time = self.up() utils.wait(dur) feed_over = self.down() feed_duration = feed_over - feed_time return (feed_time, feed_duration)
def stimulus_main(self): ## 1. present cue if 'cue' in self.this_trial.annotations: cue = self.this_trial.annotations["cue"] self.log.debug("cue light turning on") cue_start = dt.datetime.now() if cue == "red": self.panel.cue.red() elif cue == "green": self.panel.cue.green() elif cue == "blue": self.panel.cue.blue() utils.wait(self.parameters["cue_duration"]) self.panel.cue.off() cue_dur = (dt.datetime.now() - cue_start).total_seconds() cue_time = (cue_start - self.this_trial.time).total_seconds() cue_event = utils.Event( time=cue_time, duration=cue_dur, label='cue', name=cue, ) self.this_trial.events.append(cue_event) utils.wait(self.parameters["cuetostim_wait"]) ## 2. play stimulus stim_start = dt.datetime.now() self.this_trial.stimulus_event.time = ( stim_start - self.this_trial.time).total_seconds() self.panel.speaker.play() # already queued in stimulus_pre()
def sleep_main(self): """ reset expal parameters for the next day """ self.log.debug('sleeping...') self.panel.house_light.off() utils.wait(self.parameters['idle_poll_interval']) if not utils.check_time(self.parameters['light_schedule']): return 'main' else: return 'post'
def run(self): """ Checks every poll interval whether the panel should be sleeping and puts it to sleep """ while True: logger.debug("sleeping") self.experiment.panel.sleep() utils.wait(self.poll_interval) if not self.check(): break self.experiment.panel.wake()
def temp(): elapsed_time = (dt.datetime.now() - self.polling_start).total_seconds() if elapsed_time <= duration: if component.status(): self.responded_poll = True self.last_response = component.name return None utils.wait(.015) return 'main' else: return None
def run(self): """ Checks if the experiment should be sleeping or running a session and kicks off those states. """ while True: if self.experiment.check_sleep_schedule(): return self.experiment._sleep.start() elif self.experiment.check_session_schedule(): return self.experiment.session.start() else: logger.debug("idling...") utils.wait(self.poll_interval)
def trial_pre(self): """ Store data that is specific to this experiment, and compute a wait time for an intertrial interval """ stimulus = self.this_trial.stimulus.file_origin if isinstance(self.intertrial_interval, (list, tuple)): iti = np.random.uniform(*self.intertrial_interval) else: iti = self.intertrial_interval logger.debug("Waiting for %1.3f seconds" % iti) self.this_trial.annotate(stimulus_name=stimulus, intertrial_interval=iti) utils.wait(iti)
def test(self): self.reset() dur = 2.0 for output in self.outputs: output.write(True) utils.wait(dur) output.write(False) self.reset() self.reward(value=dur) self.punish(value=dur) self.speaker.queue('/usr/local/stimuli/test48k.wav') self.speaker.play() time.sleep(1.0) self.speaker.stop() return True
def stimulus_main(self): """ Queue the sound and play it """ logger.info( "Trial %d - %s - %s" % (self.this_trial.index, self.this_trial.time.strftime("%H:%M:%S"), self.this_trial.stimulus.name)) self.panel.speaker.queue(self.this_trial.stimulus.file_origin) self.panel.speaker.play() # Wait for stimulus to finish utils.wait(self.this_trial.stimulus.duration) # Stop the sound self.panel.speaker.stop()
def stimulus_main(self): """ Queue the sound and play it """ logger.info("Trial %d - %s - %s" % ( self.this_trial.index, self.this_trial.time.strftime("%H:%M:%S"), self.this_trial.stimulus.name )) self.panel.speaker.queue(self.this_trial.stimulus.file_origin) self.panel.speaker.play() # Wait for stimulus to finish utils.wait(self.this_trial.stimulus.duration) # Stop the sound self.panel.speaker.stop()
def temp(): elapsed_time = (dt.datetime.now() - self.polling_start).total_seconds() if elapsed_time <= duration: if ((elapsed_time % period) - (period / 2.0)) < 0: component.on() else: component.off() if component.status(): component.off() self.responded_poll = True self.last_response = component.name return None utils.wait(.015) return 'main' else: component.off() return None
def correction_reward_main(self): try: value = self.parameters['classes'][self.this_trial.class_]['reward_value'] * .5 reward_event = self.panel.reward(value=value) self.this_trial.reward = True ## TODO: make rewards into events # self.this_trial.events.append(reward_event) # but catch the reward errors ## note: this is quite specific to the Gentner Lab. consider ## ways to abstract this except components.HopperAlreadyUpError as err: self.this_trial.reward = True self.summary['hopper_already_up'] += 1 self.log.warning("hopper already up on panel %s" % str(err)) utils.wait(self.parameters['classes'][self.this_trial.class_]['reward_value']) self.panel.reset() except components.HopperWontComeUpError as err: self.this_trial.reward = 'error' self.summary['hopper_failures'] += 1 self.log.error("hopper didn't come up on panel %s" % str(err)) utils.wait(self.parameters['classes'][self.this_trial.class_]['reward_value']) self.panel.reset() # except components.ResponseDuringFeedError as err: # trial['reward'] = 'Error' # self.summary['responses_during_reward'] += 1 # self.log.error("response during reward on panel %s" % str(err)) # utils.wait(self.reward_dur[trial['class']]) # self.panel.reset() except components.HopperWontDropError as err: self.this_trial.reward = 'error' self.summary['hopper_wont_go_down'] += 1 self.log.warning("hopper didn't go down on panel %s" % str(err)) self.panel.reset() finally: self.panel.house_light.on() # TODO: add errors as trial events return 'post'
def timeout(self, dur=10.0): """Turn off the light for *dur* seconds Parameters ---------- dur : float, optional The amount of time (in seconds) to turn off the light. Returns ------- (datetime, float) Timestamp of the timeout and the timeout duration """ timeout_time = datetime.datetime.now() self.off() utils.wait(dur) timeout_duration = datetime.datetime.now() - timeout_time self.on() return (timeout_time, timeout_duration)
def test(self): print('reset') self.reset() dur = 2.0 for output in self.outputs: print('output %s on' % output) output.write(True) utils.wait(dur) print('output %s off' % output) output.write(False) print('reset') self.reset() print('feed') self.reward(value=dur) print('timeout') self.punish(value=dur) print('queue file') self.speaker.queue('/usr/local/stimuli/A1.wav') print('play file') self.speaker.play() return True
def test(self): print ('reset') self.reset() dur = 2.0 for output in self.outputs: print ('output %s on' % output) output.write(True) utils.wait(dur) print ('output %s off' % output) output.write(False) print ('reset') self.reset() print ('feed') self.reward(value=dur) print ('timeout') self.punish(value=dur) print ('queue file') self.speaker.queue('/usr/local/stimuli/A1.wav') print ('play file') self.speaker.play() return True
def down(self): """ Lowers the hopper. Returns ------- datetime Time at which the hopper came down Raises ------ HopperWontDropError The Hopper did not drop. """ self.event["action"] = "down" self.solenoid.write(False, event=self.event) time_down = datetime.datetime.now() utils.wait(self.max_lag) try: self.check() except HopperActiveError as e: raise HopperWontDropError(e) return time_down
def trial_post(self): '''things to do at the end of a trial''' self.this_trial.duration = (dt.datetime.now() - self.this_trial.time).total_seconds() self.analyze_trial() self.save_trial(self.this_trial) self.write_summary() utils.wait(self.parameters['intertrial_min']) # determine if next trial should be a correction trial self.do_correction = True if len(self.trials) > 0: if self.parameters['correction_trials']: if self.this_trial.correct == True: self.do_correction = False elif self.this_trial.response == 'none': if self.this_trial.type_ == 'normal': self.do_correction = self.parameters['no_response_correction_trials'] else: self.do_correction = False else: self.do_correction = False if self.check_session_schedule()==False: raise EndSession
def response_main(self): response_start = dt.datetime.now() while True: elapsed_time = (dt.datetime.now() - self.this_trial.time).total_seconds() response_time = elapsed_time - self.this_trial.stimulus_event.time if response_time > self.this_trial.annotations['max_wait']: self.panel.speaker.stop() self.this_trial.response = 'none' self.log.info('no response') return for class_, port in self.class_assoc.items(): if port.status(): self.this_trial.rt = (dt.datetime.now() - response_start).total_seconds() self.panel.speaker.stop() self.this_trial.response = class_ self.summary['responses'] += 1 response_event = utils.Event(name=self.parameters['classes'][class_]['component'], label='peck', time=elapsed_time, ) self.this_trial.events.append(response_event) self.log.info('response: %s' % (self.this_trial.response)) return utils.wait(.015)
def _poll(self, channel=None, invert=False, last_value=False, suppress_longpress=False, timeout=None, wait=None, event=None, *args, **kwargs): """ Runs a loop, querying for the boolean input to return True. Parameters ---------- channel: default channel argument to pass to _read_bool() invert: bool whether or not to invert the read value last_value: bool if the last read value was True. Necessary to suppress longpresses suppress_longpress: bool if True, attempts to suppress returning immediately if the button is still being pressed since the last call. If last_value is True, then it waits until the interface reads a single False value before allowing it to return. timeout: float the time, in seconds, until polling times out. Defaults to no timeout. wait: float the time, in seconds, to wait between subsequent reads (default no wait). Returns ------- timestamp of True read or None if timed out """ logger.debug("Begin polling from device %s" % self.device_name) if timeout is not None: start = time.time() if channel not in self.tasks: raise NIDAQmxError("Channel(s) %s not yet configured" % str(channel)) task = self.tasks[channel] task.start() while True: # Read the value - cannot use _read_bool because it must start and stop the task each time. value, bits_per_sample = task.read(1) value = value[0, 0] if invert: value = 1 - value value = bool(value == 1) if value: events.write(event) if not isinstance(value, bool): task.stop() raise ValueError("Polling for bool returned something that was not a bool") if value is True: if (last_value is False) or (suppress_longpress is False): logger.debug("Input detected. Returning") task.stop() return datetime.datetime.now() else: last_value = False if timeout is not None: if time.time() - start >= timeout: logger.debug("Polling timed out. Returning") task.stop() return None if wait is not None: utils.wait(wait)
def stimulus_post(self): self.log.debug('waiting %s secs...' % self.this_trial.annotations['min_wait']) utils.wait(self.this_trial.annotations['min_wait'])
def _poll(self, channel=None, invert=False, last_value=False, suppress_longpress=False, timeout=None, wait=None, event=None, *args, **kwargs): """ Runs a loop, querying for the boolean input to return True. Parameters ---------- channel: default channel argument to pass to _read_bool() invert: bool whether or not to invert the read value last_value: bool if the last read value was True. Necessary to suppress longpresses suppress_longpress: bool if True, attempts to suppress returning immediately if the button is still being pressed since the last call. If last_value is True, then it waits until the interface reads a single False value before allowing it to return. timeout: float the time, in seconds, until polling times out. Defaults to no timeout. wait: float the time, in seconds, to wait between subsequent reads (default no wait). Returns ------- timestamp of True read or None if timed out """ logger.debug("Begin polling from device %s" % self.device_name) if timeout is not None: start = time.time() if channel not in self.tasks: raise NIDAQmxError("Channel(s) %s not yet configured" % str(channel)) task = self.tasks[channel] task.start() while True: # Read the value - cannot use _read_bool because it must start and stop the task each time. value, bits_per_sample = task.read(1) value = value[0, 0] if invert: value = 1 - value value = bool(value == 1) if value: events.write(event) if not isinstance(value, bool): task.stop() raise ValueError( "Polling for bool returned something that was not a bool") if value is True: if (last_value is False) or (suppress_longpress is False): logger.debug("Input detected. Returning") task.stop() return datetime.datetime.now() else: last_value = False if timeout is not None: if time.time() - start >= timeout: logger.debug("Polling timed out. Returning") task.stop() return None if wait is not None: utils.wait(wait)