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 if self._check_free_food_block(): return 'free_food_block'
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 feed(self,dur=2.0): """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.lag < dur, "lag (%ss) must be shorter than duration (%ss)" % (self.lag,dur) try: self.check() except HopperInactiveError as e: raise HopperAlreadyUpError(e) feed_time = datetime.datetime.now() self.up() # includes a lag utils.wait(dur - self.lag) feed_duration = datetime.datetime.now() - feed_time self.down() # includes a lag return (feed_time,feed_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 port_name, port in self.response_ports.items(): if port.status(): self.this_trial.rt = (dt.datetime.now() - response_start).total_seconds() self.panel.speaker.stop() self.this_trial.response = port_name self.summary['responses'] += 1 response_event = utils.Event( name=port_name, 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 sound_then_feeder(self, filename="", duration=12, flash=False, flash_dur=3): """ Pairs the sound playback with the feeder coming up. Hit Ctrl+C to stop the sound or put the feeder down. :param filename: path to sound file. :param duration: duration the feeder is up (seconds) :param flash: whether or not to flash the button at the start (default False) """ if not filename: filename = self._default_sound_file self.speaker.queue(filename) if flash: self.peck_port.flash(dur=flash_dur) self.speaker.play() try: while self.speaker.output.interface.stream.is_active(): utils.wait(0.1) except KeyboardInterrupt: pass finally: self.speaker.stop() try: self.feeder.feed(duration) except KeyboardInterrupt: self.feeder.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 if self._check_free_food_block(): return 'free_food_block'
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 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 up(self): self.solenoid.write(True) utils.wait(self.lag) try: self.check() except HopperInactiveError as e: raise HopperWontComeUpError(e) return True
def timeout(self,dur=10.0): """ turn off light for a few seconds """ timeout_time = datetime.datetime.now() self.light.write(False) utils.wait(dur) timeout_duration = datetime.datetime.now() - timeout_time self.light.write(True) return (timeout_time,timeout_duration)
def trial_post(self): '''things to do at the end of a trial''' self.analyze_trial() self.save_trial(self.this_trial) self.write_summary() utils.wait(self.parameters['intertrial_min']) return None
def down(self): """ drop hopper """ self.solenoid.write(False) utils.wait(self.lag) try: self.check() except HopperActiveError as e: raise HopperWontDropError(e) return True
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 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 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 self.check_light_schedule() == False: return 'main' else: return 'post'
def _run_idle(self): if self.check_light_schedule() == False: return 'sleep' elif self.check_session_schedule(): return 'session' else: self.panel_reset() self.log.debug('idling...') utils.wait(self.parameters['idle_poll_interval']) return 'idle'
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 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 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 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(0.015) return "main" else: return None
def secondary_reinforcement(self, value=1.0): if "cue" in dir(self.panel): self.panel.cue.red() utils.wait(.05) self.panel.cue.off() self.panel.cue.red() utils.wait(.05) self.panel.cue.off() return else: return self.panel.center.flash(dur=value)
def calibrate(self): self.peck_port.off() while True: is_pecked = self.peck_port.status() if is_pecked: current_time = dt.datetime.now() print("%s: Pecked!" % current_time.strftime("%H:%M:%S")) self.peck_port.on() utils.wait(0.05) self.peck_port.off()
def secondary_reinforcement(self,value=1.0): if "cue" in dir(self.panel): self.panel.cue.red() utils.wait(.05) self.panel.cue.off() self.panel.cue.red() utils.wait(.05) self.panel.cue.off() return else: return self.panel.center.flash(dur=value)
def flash(self,dur=1.0,isi=0.1): """ flash the LED """ 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 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/A1.wav") self.speaker.play() return True
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('/home/pi/test.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 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(0.015) return "main" else: component.off() return None
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 feed(self,dur=2.0): """Performs a feed arguments: feedsecs -- duration of feed in seconds (default: %default) """ assert self.lag < dur, "lag (%ss) must be shorter than duration (%ss)" % (self.lag,dur) try: self.check() except HopperInactiveError as e: raise HopperAlreadyUpError(e) feed_time = datetime.datetime.now() self.up() # includes a lag utils.wait(dur - self.lag) feed_duration = datetime.datetime.now() - feed_time self.down() # includes a lag return (feed_time,feed_duration)
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 _poll(self, channel, timeout=None, wait=None, suppress_longpress=True, **kwargs): """ runs a loop, querying for pecks. returns peck time or None if polling times out :param channel: the channel from which to read :param timeout: the time, in seconds, until polling times out. Defaults to no timeout. :param wait: the time, in seconds, between subsequent reads. Defaults to 0. :param suppress_longpress: only return a successful read if the previous read was False. This can be helpful when using a button, where a press might trigger multiple times. :return: timestamp of True read """ if timeout is not None: start = time.time() logger.debug("Begin polling from device %s" % self.device_name) while True: if not self._read_bool(channel): logger.debug("Polling: %s" % False) # Read returned False. If the channel was previously "held" then that flag is removed if self._state[channel]["held"]: self._state[channel]["held"] = False else: logger.debug("Polling: %s" % True) # As long as the channel is not currently held, or longpresses are not being supressed, register the press if (not self._state[channel]["held"]) or ( not suppress_longpress): break if timeout is not None: if time.time( ) - start >= timeout: # Return GoodNite exception? logger.debug("Polling timed out. Returning") return None # Wait for a specified amount of time before continuing on with the next loop if wait is not None: utils.wait(wait) self._state[channel]["held"] = True logger.debug("Input detected. Returning") return datetime.datetime.now()
def timeout(self, dur=10.0): """Turn off the light for *dur* seconds Keywords ------- 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.light.write(False) utils.wait(dur) timeout_duration = datetime.datetime.now() - timeout_time self.light.write(True) return (timeout_time, timeout_duration)
def down(self): """Lowers the hopper. Returns ------- bool True if the hopper drops. Raises ------ HopperWontDropError The Hopper did not drop. """ self.solenoid.write(False) utils.wait(self.lag) try: self.check() except HopperActiveError as e: raise HopperWontDropError(e) return True
def timeout(self,dur=10.0): """Turn off the light for *dur* seconds Keywords ------- 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.light.write(False) utils.wait(dur) timeout_duration = datetime.datetime.now() - timeout_time self.light.write(True) return (timeout_time,timeout_duration)
def up(self): """Raises the hopper up. Returns ------- bool True if the hopper comes up. Raises ------ HopperWontComeUpError The Hopper did not raise. """ self.solenoid.write(True) utils.wait(self.lag) try: self.check() except HopperInactiveError as e: raise HopperWontComeUpError(e) return True
def test_audio(self, filename="", repeat=False): if not filename: filename = self._default_sound_file print("Testing sound playback with %s" % filename) while True: self.speaker.queue(filename) self.speaker.play() try: while self.speaker.output.interface.stream.is_active(): utils.wait(0.1) except KeyboardInterrupt: return finally: self.speaker.stop() if not repeat: break
def down(self): """Lowers the hopper. Returns ------- bool True if the hopper drops. Raises ------ HopperWontDropError The Hopper did not drop. """ self.solenoid.write(False) time_down = datetime.datetime.now() utils.wait(self.max_lag) try: self.check() except HopperActiveError as e: raise HopperWontDropError(e) return time_down
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 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. """ logger.debug("Feeding..") 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 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 stimulus_post(self): self.log.debug('waiting %s secs...' % self.this_trial.annotations['min_wait']) utils.wait(self.this_trial.annotations['min_wait'])