class Controller: REFRESH_INTERVAL = 300 #ms def __init__(self, session): self.app = wx.App(False) self.session = session self.view = View(None, name=self.session.subj.name, n_lick_show=self.session.lr.ACCUM_SIZE) # bindings self.view.start_button.Bind(wx.EVT_BUTTON, self.run_session) self.view.pause_button.Bind(wx.EVT_BUTTON, self.pause_session) self.view.rewardl_but.Bind(wx.EVT_BUTTON, lambda evt, temp=self.session.L: self.give_reward(evt, temp)) self.view.rewardr_but.Bind(wx.EVT_BUTTON, lambda evt, temp=self.session.R: self.give_reward(evt, temp)) self.view.puffl_but.Bind(wx.EVT_BUTTON, lambda evt, temp=self.session.L: self.give_puff(evt, temp)) self.view.puffr_but.Bind(wx.EVT_BUTTON, lambda evt, temp=self.session.R: self.give_puff(evt, temp)) self.view.Bind(wx.EVT_CLOSE, self.on_close) self.view.Show() def run(self): self.trial_n = self.session.trial_idx self.update_vals() self.app.MainLoop() def give_reward(self, evt, side): self.session.spout.go(side) def give_puff(self, evt, side): self.session.stimulator.go(side, dur=self.session.stim_duration) def pretty_time(self, t): if t<60: return '%0.0f s'%t else: return '%0.0f m, %0.0f s'%(np.floor(t/60.),t%60.) def update_vals(self): # values self.view.trial_n_widg.SetValue("%s (%s)"%(str(self.session.valid_trial_idx),str(self.session.trial_idx))) self.view.session_runtime_widg.SetValue(self.pretty_time(self.session.session_runtime)) self.view.trial_runtime_widg.SetValue(self.pretty_time(self.session.trial_runtime)) # plots self.view.set_lick_data(self.session.lr.get_accum()) # movie self.view.panel_mov.set_frame(self.session.cam.get_current_frame(self.session.cam.cS)) # trial trn = self.session.trial_idx if trn != self.trial_n and self.session.session_on: self.trial_n = trn if self.session.use_trials: self.view.set_trial_data(self.session.trials[self.trial_n], self.session.stim_phase_intro_duration, self.session.phase_durations[self.session.PHASE_DELAY], self.session.stim_phase_end_duration) self.view.set_perf_data(*self.session.get_cum_performance()) self.view.rewarded_widg.SetValue(str(self.session.rewards_given)) self.view.perc_widg.SetValue(' / '.join(['%0.2f [%i]'%(p,n) for p,n in zip(self.session.percentages[::-1], self.session.side_ns[::-1])])) self.view.bias_widg.SetValue(' / '.join(['%0.2f'%s for s in self.session.bias_correction_percentages[::-1]])+' [%i]'%self.session.bias_correction_window) self.view.pvalid_widg.SetValue('%0.2f'%self.session.perc_valid) # controls if self.session.session_complete or self.session.session_kill: self.view.start_button.Disable() # pauses if self.session.paused: self.view.pause_button.SetLabel('Unpause') self.view.pause_button.SetBackgroundColour((0,255,0)) self.view.start_button.Disable() elif not self.session.paused: self.view.pause_button.SetLabel('Pause') self.view.pause_button.SetBackgroundColour((0,150,150)) if self.session.session_on and not self.session.session_kill: self.view.start_button.Enable() self.update_timer = wx.CallLater(self.REFRESH_INTERVAL, self.update_vals) def run_session(self, evt): if not self.session.session_on: self.run_th = threading.Thread(target=self.session.run) self.run_th.start() self.view.start_button.SetLabel('End Session') self.view.start_button.SetBackgroundColour((255,0,0)) self.view.pause_button.Enable() elif self.session.session_on: self.session.session_kill = True self.view.start_button.Disable() self.view.puffr_but.Disable() self.view.puffl_but.Disable() self.view.rewardr_but.Disable() self.view.rewardl_but.Disable() self.view.pause_button.Disable() def pause_session(self, evt): if not self.session.paused: self.session.paused += 1 self.view.pause_button.SetLabel('Unpause') self.view.pause_button.SetBackgroundColour((0,255,0)) self.view.start_button.Disable() elif self.session.paused: self.session.paused = max(self.session.paused-1,0) self.view.pause_button.SetLabel('Pause') self.view.pause_button.SetBackgroundColour((0,100,200)) self.view.start_button.Enable() def on_close(self, evt): if self.session.session_on: dlg = wx.MessageDialog(self.view, message='End session before closing interface.', caption='Session is active.', style=wx.OK) res = dlg.ShowModal() dlg.Destroy() else: dlg = wx.MessageDialog(self.view, message="Some data may be lost.", caption="Exit Experiment?", style=wx.OK|wx.CANCEL) result = dlg.ShowModal() dlg.Destroy() if result == wx.ID_OK: self.update_timer.Stop() self.view.Destroy()