class MCC152_DIO: def __init__(self, params): try: self.di_ch = params['di_ch'] # convert int to tuple if isinstance(self.di_ch, int): self.di_ch = (self.di_ch, ) self.do_ch = params['do_ch'] # convert int to tuple if isinstance(self.do_ch, int): self.do_ch = (self.do_ch, ) except KeyError: logging.error(KeyError, exc_info=True) self.HAT = None self.callback = None if 'timer' in params: self.timer = params['timer'] else: self.timer = Timer() if 'timestamping' in params: self.di_tstamp = [] self.di_series = [] self.timestamping = True else: self.timestamping = False # data for input interruption # interrupt_counter: frame_counter self.interrupt_counter = 0 self.interrupt_time = 0 # since mc152 interrupt time is too slow to detect fast interrupts # between a millisecond, I set a sleep time that allows to get # interrupt signals that occurs only longer than the min interrupt interval set below if 'min_interrupt_interval' in params: self.min_interrupt_interval = params['min_interrupt_interval'] else: self.min_interrupt_interval = 10 # millsecond self.init_dev() def init_dev(self): address = select_hat_device(HatIDs.MCC_152) self.HAT = mcc152(address) # Reset the DIO to defaults (all channels input, pull-up resistors # enabled). self.HAT.dio_reset() # Read the initial input values so we don't trigger an interrupt when # we enable them. self.HAT.dio_input_read_port() # set digital ouptput channels for ch in self.do_ch: try: self.HAT.dio_config_write_bit(ch, DIOConfigItem.DIRECTION, 0) # since default output register value is 1, # reset to 0 self.write_outputvalue(ch, 0) except (HatError, ValueError): logging.error( 'could not configure the channel{} as output'.format(ch)) sys.exit() # set digital iput channels as latched input for ch in self.di_ch: try: self.HAT.dio_config_write_bit(ch, DIOConfigItem.DIRECTION, 1) # Enable latched inputs so we know that a value changed even if it changes # back to the original value before the interrupt callback. self.HAT.dio_config_write_bit(ch, DIOConfigItem.INPUT_LATCH, 1) # interrupt enabled self.HAT.dio_config_write_bit(ch, DIOConfigItem.INT_MASK, 0) except (HatError, ValueError): logging.error( 'could not configure the channel{} as output'.format(ch)) sys.exit() self.callback = HatCallback(self.interrupt_callback) def interrupt_callback(self, userdat): """ def interrupt_callback(self,userdat): interrupt callback function This function is only for interrupt counter """ interrupt_ch = list([]) status = self.HAT.dio_int_status_read_port() if status != 0: for i in self.di_ch: if (status & (1 << i)) != 0: interrupt_ch.append(i) # Read the inputs to clear the active interrupt. dio_input_value = self.HAT.dio_input_read_port() if self.timestamping: self.di_tstamp.insert(self.interrupt_counter, self.timer.elapsed_time()) self.di_series.insert(self.interrupt_counter, dio_input_value) interrupt_timestamp = self.timer.elapsed_time() framedur = interrupt_timestamp - self.interrupt_time if framedur > self.min_interrupt_interval: self.interrupt_counter += 1 self.interrupt_time = interrupt_timestamp logging.debug("DIcounter:{}-Ch:{}, port value: 0x{:02X},{}-framedur:{}"\ .format(self.interrupt_counter,interrupt_ch,\ dio_input_value,dio_input_value,framedur)) return def get_interrupt_counter(self): return self.interrupt_counter #return self.interrupt_counter[0] def reset_timer(self): """ def reset_timer(self): reset timer """ self.timer.start() def di_acqstart(self): """ def di_acqstart(self): digital input acqusition start """ interrupt_callback_enable(self.callback, []) logging.info('DI acqusition started') def di_acqstop(self): """ def di_acqstop(self): digital input acqusition stop """ self.HAT.dio_reset() interrupt_callback_disable() logging.info('DI acqusition stopped') def write_outputvalue(self, ch, value): """ def write_outputvalue(self, ch, value): output value at channel ch return: timestamp """ if bool(self.do_ch): try: self.HAT.dio_output_write_bit(ch, value) timestamp = self.timer.elapsed_time() logging.debug('DO ch{} : {}-tstamp:{}'.format( ch, value, timestamp)) except (HatError, ValueError): raise else: logging.warning('DO channel is empty.') return timestamp def read_outputvalue(self, ch): """ def read_outputvalue(self, ch, value): read output value at channel ch return: timestamp """ if bool(self.do_ch): try: outputvalue = self.HAT.dio_output_read_bit(ch) timestamp = self.timer.elapsed_time() logging.debug('DO ch{} : {}-tstamp:{}'.format( ch, value, timestamp)) except (HatError, ValueError): raise else: logging.error('DO channel is empty.', exc_info=True) return outputvalue, timestamp
class Controlframe: def __init__(self, filename): self.master = tk.Tk() self.master.protocol("WM_DELETE_WINDOW", self.on_closing) self.hwin = tk.Frame(self.master) self.fn = filename self.paramwindow = tk.Toplevel(self.master) self.paramframe = Paramframe(self.paramwindow, self.fn) self.hcomp = {} self.create_uimodules() self.hwin.pack() self.stepper = None self.dio = None self.daq = None self.motor_time = [] # motor start and stop time self.motor_speed = [] # motor speed self.elec_time = [] # record for elecstim onset time and duration self.timer = Timer() # set timer self.motor_timer = None def on_closing(self): if self.stepper: self.stepper.close() if self.daq: self.daqstop() self.master.destroy() print("Window closed") def save_trialdata(self): """ def save_trialdata(self): save trial data for motor rotation time (start, end) and motor speed and elecstim (start, duration) """ output_tr = { 'motor_time': self.motor_time, 'motor_speed': self.motor_speed, 'elec_time': self.elec_time } outpar = self.paramframe.data outpar.update({'trial_data': output_tr}) if outpar['daqparam']['timer']: outpar['daqparam']['timer'] = [] if self.daq and self.daq.fn: fn = self.daq.fn idx = fn.find('.dat') outpar_fn = fn[:idx] + '.json' else: import datetime x = datetime.datetime.now() datfname = x.strftime("%X") daqparam = self.paramframe.data['daqparam'] if daqparam['save_dir']: save_dir = daqparam['save_dir'] else: save_dir = '.' outpar_fn = path.join(save_dir, datfname.replace(':', '') + '.json') with open(outpar_fn, 'wt') as envf: j = json.dumps(outpar, indent=4) envf.write(j) tk.messagebox.showinfo("SAVE", "Trialdata_saved in:{}".format(outpar_fn)) def create_uimodules(self): h = tk.Button(self.hwin, text='DAQ start', command=self.daqstart) h.grid(row=0, column=0, pady=4) self.hcomp['daqstart_b'] = h h = tk.Button(self.hwin, text='DAQ stop', command=self.daqstop) h.grid(row=0, column=1, pady=4) self.hcomp['daqstop_b'] = h h = tk.Button(self.hwin, text='motor_init', command=self.motor_init) h.grid(row=1, column=0, pady=4) self.hcomp['motor_init'] = h h = tk.Button(self.hwin, text='motor_det', command=self.motor_detach) h.grid(row=1, column=1, pady=4) self.hcomp['motor_detach'] = h motor_set = {'speed': 50, 'accel': 250, 'dur': 30} h = Entryframe(self.hwin, motor_set, 'motor_setting') h.grid(row=2, rowspan=3, column=0, columnspan=2, padx=5, pady=5) self.hcomp['motor_setting'] = h h = tk.Button(self.hwin, text='motor_run', command=self.motor_run) h.grid(row=5, column=0, pady=4) self.hcomp['motor_run'] = h h = tk.Button(self.hwin, text='motor_stop', command=self.motor_stop) h.grid(row=5, column=1, pady=4) self.hcomp['motor_stop'] = h DIO_set = {'Ch.': 6, 'dur': 0, 'delay': 0, 'motor_delay': 0} h = Entryframe(self.hwin, DIO_set, 'DIO_setting') h.grid(row=6, columnspan=2, padx=2, pady=5) self.hcomp['elec'] = h h = tk.Button(self.hwin, text='DIO_init', command=self.DIO_init) h.grid(row=7, column=0, pady=4) self.hcomp['DIO_init'] = h h = tk.Button(self.hwin, text='elec_stim', command=self.DIO_output) h.grid(row=7, column=1, pady=4) self.hcomp['elec_stim'] = h h = tk.Button(self.hwin, text='save_trialdata', command=self.save_trialdata) h.grid(row=8, column=0, pady=4) self.hcomp['save_trialdata'] = h def daqstart(self): if self.daq: self.daq = None daqparam = self.paramframe.data['daqparam'] daqparam['timer'] = self.timer self.daq = MCC118(daqparam) self.daq.acq_start() tk.messagebox.showinfo("DAQ-Info", "DAQ_started. filename:{}".format(self.daq.fn)) h = self.hcomp['daqstart_b'] h['state'] = tk.DISABLED def daqstop(self): if self.daq: self.daq.acq_stop() h = self.hcomp['daqstart_b'] h['state'] = tk.NORMAL def motor_init(self): if not self.stepper: self.stepper = stepper.Stepperwrapper() h = self.hcomp['motor_init'] h['state'] = tk.DISABLED def motor_detach(self): if self.stepper: self.stepper.close() self.stepper = None tk.messagebox.showinfo("Info", "motor detached") h = self.hcomp['motor_init'] h['state'] = tk.NORMAL def motor_run(self): if self.stepper: self.hcomp['motor_setting'].update_par() #tk.messagebox.showinfo("test",str(hf.hcomp['motor_setting'].data['speed'])) speed = self.hcomp['motor_setting'].hcomp['speed'].get() accel = self.hcomp['motor_setting'].hcomp['accel'].get() dur = self.hcomp['motor_setting'].hcomp['dur'].get() dur = float(dur) self.stepper.setEngaged(False) self.stepper.setAcceleration(float(accel)) self.stepper.setVelocityLimit(float(speed)) # record trial info motor_start_time = self.timer.elapsed_time() self.motor_time.append(motor_start_time) self.motor_speed.append(float(speed)) self.stepper.setEngaged(True) self.hcomp['motor_setting'].entry_disable() if dur > 0: self.motor_timer = Threadworker(self.motor_stop_timer) self.motor_timer.start() else: tk.messagebox.showinfo("Info", "motor not initialized") def motor_stop_timer(self): self.hcomp['motor_setting'].update_par() dur = self.hcomp['motor_setting'].hcomp['dur'].get() dur = float(dur) if dur > 0: t0 = self.timer.elapsed_time() t = t0 while self.motor_timer.running() and ( t - t0) < dur * 1000: #timer is millisecond sleep(0.05) t = self.timer.elapsed_time() logging.debug('et:{}'.format(t - t0)) if (t - t0) > dur * 1000: # when entire duration pass, stop self.motor_stop() def motor_stop(self): if self.stepper: self.motor_time.append(self.timer.elapsed_time()) self.stepper.setVelocityLimit(0) #self.stepper.setAcceleration(0) self.stepper.setEngaged(False) self.hcomp['motor_setting'].entry_enable() if self.motor_timer and self.motor_timer.running(): self.motor_timer.stop() #def save_daq(self, fn=None): #import pandas as pd #if fn: #file_name = './motor_data/'+fn #else: #import datetime #x = datetime.datetime.now() #datfname = x.strftime("%X") #file_name = '../motor_data/'+datfname.replace(':','')+'.csv' #data = np.concatenate(self.daq.data, axis =0) #t = np.concatenate(self.daq.t, axis =0) #daqparam = hf.paramframe.data['daqparam'] #out ={} #for i,ch in enumerate(daqparam['ai_ch']): # out['CH'+ str(ch)]=data[:,i] #df = pd.DataFrame(out, index = t) #df.index.name ='Time(sec)' #df.to_csv(file_name, sep=',') def DIO_init(self): if not self.dio: dioparam = self.paramframe.data['dioparam'] self.dio = MCC152_DIO(dioparam) else: self.dio.init_dev() def DIO_output(self): channels = self.paramframe.data['dioparam']['do_ch'] ch = self.hcomp['elec'].hcomp['Ch.'].get() ch = int(ch) #print(type(ch)) #ch = int(ch) #tk.messagebox.showinfo("Info",type(ch)) dur_sec = float(self.hcomp['elec'].hcomp['dur'].get()) delay = float(self.hcomp['elec'].hcomp['delay'].get()) motor_delay = float(self.hcomp['elec'].hcomp['motor_delay'].get()) if ch in channels and self.dio: sleep(delay) self.elec_time.append(self.timer.elapsed_time()) self.elec_time.append(dur_sec) for i in range(5): self.dio.write_outputvalue(ch, 1) sleep(dur_sec) self.dio.write_outputvalue(ch, 0) else: msg = "ch" + str(ch) + " not opened or device not attached" tk.messagebox.showinfo("Info", msg) # motor_delay<0, motor behavior is independent of elec stim # motor_delay==0, motor stops immediately # motor_delay>0, motor stops 'motor_delay' after elec stim if motor_delay >= 0: sleep(motor_delay) self.motor_stop()
class Trigger: """ generic class for tirgger generation""" def __init__(self, dio, params): if isinstance(dio, MCC152_DIO): self.dio = dio else: raise ValueError('not proper dio object assigned') if 'timer' in params: self.timer = params['timer'] else: self.timer = Timer() # setting a common timer in dio self.dio.timer = self.timer self.init_dio() def init_dio(self): # start digital input acquisition i.e., 2p-frame triggers self.dio.di_acqstart() def clear_dio(self): self.dio.di_acqstop() def elapsed_time(self, start=0): return self.timer.elapsed_time() - start def get_frame_counter(self): # 2p-frame counter return self.dio.get_interrupt_counter() def wait_delayframe(self, nframe_delay, sleeptime=0.01): """ def wait_delayframe(self, nframe_delay, sleeptime=0.01): wait until nframe_delay """ try: while self.dio.get_interrupt_counter() < nframe_delay: #logging.debug('DIO_interrupt_counter:{}'.\ # format(self.dio.get_interrupt_counter())) sleep(sleeptime) except KeyboardInterrupt: print('\nKeyboard Interruption\n') timestamp = self.timer.elapsed_time() return timestamp def write_trigger(self, ch, timedur=0): """ write output trigger""" timestamp = self.timer.elapsed_time() self.write_1(ch) if timedur > 0: sleep(timedur) self.write_0(ch) return timestamp def toggle_state(self, ch): """ flip digital output value from the current state""" outputvalue = self.dio.read_outputvalue(ch) if outputvalue == 1: self.write_0(ch) else: self.write_1(ch) timestamp = self.timer.elapsed_time() return timestamp def write_1(self, ch): self.dio.write_outputvalue(ch, 1) def write_0(self, ch): self.dio.write_outputvalue(ch, 0) def reset_dio_output(self): for ich in self.dio.do_ch: self.dio.write_0(ich) __write_trigger = write_trigger
class MCC118(DAQ): """ mcc118""" def __init__(self, params): #super(DAQ,self).__init__(params) super().__init__(params) try: self.timeout = params['timeout'] self.acq_dur = params['acq_dur'] # acquistion segment duration except KeyError: raise if 'timer' in params: self.timer = params['timer'] else: self.timer = Timer() self.read_request_size =[] # will be converted from self.acq_dur from init_daq self.hat = [] self.worker = Threadworker(self.acq_start) self.worker.setName('DAQthreader_ch'+str(self.ai_ch)) self.init_daq() def init_daq(self): try: address = select_hat_device(HatIDs.MCC_118) self.hat = mcc118(address) num_channels = len(self.ai_ch) self.scan_rate = self.hat.a_in_scan_actual_rate(num_channels, self.scan_rate) self.read_request_size = int(self.scan_rate*self.acq_dur) except (NameError, SyntaxError): pass def reset_timer(self): """ def reset_timer(self): reset timer """ self.timer.start() def record_cont(self): """ def record_cont(self): recording continously while scan_status is running """ nch = len(self.ai_ch) scan_status = self.hat.a_in_scan_status() while self.worker.running() & scan_status.running : scan_status = self.hat.a_in_scan_status() nsample =scan_status.samples_available if nsample>= self.read_request_size: read_result = self.hat.a_in_scan_read_numpy(READ_ALL_AVAILABLE, self.timeout) self.data_acqtime[self.acq_counter] = self.timer.elapsed_time() nsample = int(len(read_result.data) / nch) # self.data_len[self.acq_counter] =nsample # Check for an overrun error if read_result.hardware_overrun: print('\n\nHardware overrun\n') elif read_result.buffer_overrun: print('\n\nBuffer overrun\n') self.data = np.reshape(read_result.data,(nsample,nch)) timeoff = self.total_nsample_perchannel/self.scan_rate self.t = timeoff + np.array(range(0,nsample))/self.scan_rate workername = self.worker.getName() #logging.debug('{}: counter:{}, nsample:{}, abstime:{}'.format(workername,self.acq_counter, nsample, self.data_acqtime[self.acq_counter])) self.worker.set_datflag() self.total_nsample_perchannel += nsample self.acq_counter +=1 sleep(self.acq_dur*0.9) else: sleep(0.05) def record_N_sample(self): """ def record_N_sample(self): read N samples """ nch = len(self.ai_ch) scan_status = self.hat.a_in_scan_status() total_samples_read =0 segment_size = int(self.scan_rate* 0.1) #set segment size to 100msec N = self.read_request_size if self.worker.running() & scan_status.running : while total_samples_read <N: read_result = self.hat.a_in_scan_read_numpy(segment_size, self.timeout) self.data_acqtime[self.acq_counter] = self.timer.elapsed_time() nsample = int(len(read_result.data) / nch) # # Check for an overrun error if read_result.hardware_overrun: print('\n\nHardware overrun\n') elif read_result.buffer_overrun: print('\n\nBuffer overrun\n') dataseg = np.reshape(read_result.data,(nsample,nch)) timeoff = self.total_nsample_perchannel/self.scan_rate tseg = timeoff + np.array(range(0,nsample))/self.scan_rate self.t = np.hstack((self.t,tseg)) self.data = np.vstack((self.data,dataseg)) self.data_len[self.acq_counter] =nsample workername = self.worker.getName() #logging.debug('{}: counter:{}, nsample:{}, abstime:{}'.format(workername,self.acq_counter, nsample, self.data_acqtime[self.acq_counter])) self.total_nsample_perchannel += nsample self.acq_counter +=1 sleep(segment_size*0.9) self.worker.set_datflag() # set data_ready_flag def wait_for_trigger(self): """ Monitor the status of the specified HAT device in a loop until the triggered status is True or the running status is False. """ # Read the status only to determine when the trigger occurs. is_running = True is_triggered = False while is_running and not is_triggered: status = self.hat.a_in_scan_status() is_running = status.running is_triggered = status.triggered def record_withtrigger(self): while self.worker.running(): self.wait_for_trigger() self.record_N_sample() def acq_start(self): """ def acq_start(self): acqusition start """ channel_mask = chan_list_to_mask(self.ai_ch) if self.mode =='continuous': samples_per_channel = 0 options = OptionFlags.CONTINUOUS self.hat.a_in_scan_start(channel_mask, samples_per_channel, self.scan_rate,options) self.record_cont() elif self.mode=='trigger': samples_per_channel = self.read_request_size options = OptionFlags.EXTTRIGGER trigger_mode = TriggerModes.RISING_EDGE self.hat.trigger_mode(trigger_mode) self.hat.a_in_scan_start(channel_mask, samples_per_channel, self.scan_rate,options) self.record_withtrigger() elif self.mode =='finite': samples_per_channel = self.read_request_size options = OptionFlags.DEFAULT self.hat.a_in_scan_start(channel_mask, samples_per_channel, self.scan_rate,options) self.record_N_sample() else: print('not implmented\n') raise self.worker.clear_datflag() def acq_stop(self): self.hat.a_in_scan_stop() self.worker.stop() def acq_cleanup(self): self.hat.a_in_scan_cleanup() #READ_ALL_AVAILABLE = -1 #class DAQ: # """ DAQ""" # # def __init__(self, params): # try: # self.ch = params['channels'] # self.scan_rate = params['scan_rate'] # self.mode = params['mode'] # continuous, trigger, finite # self.timeout = params['timeout'] # self.acq_dur = params['acq_dur'] # acquistion segment duration # except KeyError: # raise # # self.read_request_size =[] # self.hat = [] # # self.data =[] # segment data # self.t =[] # acquisition relative time for segment # self.acq_counter = 0 # segment counter # self.total_nsample_perchannel =0 # total number of samples per channel # # if 'timer' in params: # self.timer = params['timer'] # else: # self.timer = Timer() # # self.data_acqtime ={} #relative time of data-segment acquisition # self.data_len = {} # sample number per each segment # #pdb.set_trace() # self.worker = Threadworker(self.acq_start) # self.worker.setName('DAQthreader_ch'+str(self.ch)) # #self.worker = Processworker(self.acq_start) # # # self.init_daq() # # def init_daq(self): # try: # address = select_hat_device(HatIDs.MCC_118) # self.hat = mcc118(address) # #pdb.set_trace() # num_channels = len(self.ch) # self.read_request_size = int(self.scan_rate*self.acq_dur) # self.scan_rate = self.hat.a_in_scan_actual_rate(num_channels, self.scan_rate) # # # # except (NameError, SyntaxError): # pass # # # def reset_timer(self): # """ # def reset_timer(self): # reset timer # """ # self.timer.start() # # def record_cont(self): # """ # def record_cont(self): # recording continously while scan_status is running # """ # # nch = len(self.ch) # # scan_status = self.hat.a_in_scan_status() # while self.worker.running() & scan_status.running : # # scan_status = self.hat.a_in_scan_status() # nsample =scan_status.samples_available # # if nsample>= self.read_request_size: # read_result = self.hat.a_in_scan_read_numpy(READ_ALL_AVAILABLE, self.timeout) # self.data_acqtime[self.acq_counter] = self.timer.elapsed_time() # nsample = int(len(read_result.data) / nch) # # self.data_len[self.acq_counter] =nsample # # # Check for an overrun error # if read_result.hardware_overrun: # print('\n\nHardware overrun\n') # elif read_result.buffer_overrun: # print('\n\nBuffer overrun\n') # # self.data = np.reshape(read_result.data,(nsample,nch)) # timeoff = self.total_nsample_perchannel/self.scan_rate # self.t = timeoff + np.array(range(0,nsample))/self.scan_rate # # workername = self.worker.getName() # #logging.debug('{}: counter:{}, nsample:{}, abstime:{}'.format(workername,self.acq_counter, nsample, self.data_acqtime[self.acq_counter])) # # self.worker.set_datflag() # # self.total_nsample_perchannel += nsample # self.acq_counter +=1 # sleep(self.acq_dur*0.9) # else: # sleep(0.05) # # # def record_N_sample(self): # """ # def record_N_sample(self): # read N samples # """ # # nch = len(self.ch) # scan_status = self.hat.a_in_scan_status() # total_samples_read =0 # segment_size = int(self.scan_rate* 0.1) #set segment size to 100msec # N = self.read_request_size # # if self.worker.running() & scan_status.running : # while total_samples_read <N: # read_result = self.hat.a_in_scan_read_numpy(segment_size, self.timeout) # nsample = int(len(read_result.data) / nch) # # # Check for an overrun error # if read_result.hardware_overrun: # print('\n\nHardware overrun\n') # elif read_result.buffer_overrun: # print('\n\nBuffer overrun\n') # # dataseg = np.reshape(read_result.data,(nsample,nch)) # timeoff = self.total_nsample_perchannel/self.scan_rate # tseg = timeoff + np.array(range(0,nsample))/self.scan_rate # self.t = np.hstack((self.t,tseg)) # self.data = np.vstack((self.data,dataseg)) # self.data_len[self.acq_counter] =nsample # # workername = self.worker.getName() # #logging.debug('{}: counter:{}, nsample:{}, abstime:{}'.format(workername,self.acq_counter, nsample, self.data_acqtime[self.acq_counter])) # # self.total_nsample_perchannel += nsample # self.acq_counter +=1 # sleep(segment_size*0.9) # self.worker.set_datflag() # set data_ready_flag # # # def wait_for_trigger(self): # """ # Monitor the status of the specified HAT device in a loop until the # triggered status is True or the running status is False. # """ # # Read the status only to determine when the trigger occurs. # is_running = True # is_triggered = False # while is_running and not is_triggered: # status = self.hat.a_in_scan_status() # is_running = status.running # is_triggered = status.triggered # # # # def record_withtrigger(self): # while self.worker.running(): # self.wait_for_trigger() # self.record_N_sample() # # # def acq_start(self): # """ # def acq_start(self): # acqusition start # """ # # # channel_mask = chan_list_to_mask(self.ch) # # if self.mode =='continuous': # samples_per_channel = 0 # options = OptionFlags.CONTINUOUS # # self.hat.a_in_scan_start(channel_mask, samples_per_channel, self.scan_rate,options) # self.record_cont() # # # elif self.mode=='trigger': # samples_per_channel = self.read_request_size # options = OptionFlags.EXTTRIGGER # trigger_mode = TriggerModes.RISING_EDGE # # self.hat.trigger_mode(trigger_mode) # # self.hat.a_in_scan_start(channel_mask, samples_per_channel, self.scan_rate,options) # self.record_withtrigger() # # elif self.mode =='finite': # samples_per_channel = self.read_request_size # options = OptionFlags.DEFAULT # self.hat.a_in_scan_start(channel_mask, samples_per_channel, self.scan_rate,options) # self.record_N_sample() # # # else: # print('not implmented\n') # raise # self.worker.clear_datflag() # # def acq_stop(self): # self.hat.a_in_scan_stop() # self.worker.stop() # def acq_cleanup(self): # self.hat.a_in_scan_cleanup()
class King(): """ represents the king """ def __init__(self, screen, levels): # Static self.screen = screen self.sprites = King_Sprites().king_images self.levels = levels self.timer = Timer() self.creative_speed = 10 self.walkAngles = {"right" : math.pi/2, "left" : -math.pi/2} self.jumpAngles = {'up' : 0, 'left' : -math.pi/3, 'right' : math.pi/3} # Booleans self.isWalk = False self.isCrouch = False self.isFalling = False self.isContact = False self.isSplat = True self.isDance = False self.isLookUp = False self.isSnatch = False self.isHoldingUpHands = False self.isHoldingBabe = False self.isAdmiring = False self.isWearingCrown = False self.collided = False self.jumpParticle = False self.lastCollision = None self.collideTop = False self.collideRight = False self.collideLeft = False self.collideBottom = False self.collideRamp = False self.isJump = False self.isLanded = False # Stats self.time = 0 self.jumps = 0 self.falls = 0 # Animation self.x, self.y = 230, 298 self.width, self.height = 32, 32 self.rect_x, self.rect_y = self.x + 1, self.y + 7 self.rect_width, self.rect_height = self.width - 12, self.height - 8 self.direction = "right" self.danceCount = 0 self.walkCount = 0 self.jumpCount = 0 self.splatCount = 0 self.umbrellaCount = 0 self.maxJumpCount = 30 self.walkSpeed = 1.4 self.maxSpeed = 11 self.maxSlopeSpeed = 7 self.idle_counter = 0 self.idle_time = 300 self.idle_length = 200 self.splatDuration = 0 self.current_image = self.sprites[self.direction]["King_Fell"] self.mask = pygame.mask.from_surface(self.current_image) # Particles self.jump_particle = King_Particle("images\\particles\\jump_particle.png", 5, 1, 32) self.snow_jump_particle = King_Particle("images\\particles\\snow_jump_particle.png", 4, 3, 36) self.level_change = 0 # Audio self.channel = pygame.mixer.Channel(7) self.audio = King_Audio().audio # Physics self.physics = Physics() self.speed, self.angle = 0, 0 self.elasticity, self.angle_elasticity = 0.925, 0.5 self.charge_time = 0 @property def rect(self): return pygame.Rect((self.rect_x, self.rect_y, self.rect_width, self.rect_height)) def blitme(self): self.x = self.rect.x - 5 self.y = self.rect.y - 9 if self.direction == "left": self.x -= 1 if self.isFalling: self.y += 4 if self.isHoldingBabe: self.x -= 30 self.y -= 30 self.screen.blit(self.current_image, (self.x, self.y)) if os.environ.get("hitboxes"): pygame.draw.rect(self.screen, (255, 0, 0), self.rect, 1) if not self.level_change: self.jump_particle.blitme(self.screen) self.snow_jump_particle.blitme(self.screen) else: self.jump_particle.reset() self.snow_jump_particle.reset() def update(self, command=None, agentCommand=None): if os.environ.get("mode") == "normal": if not self.isFalling and not self.levels.ending: self._check_events(agentCommand) elif self.levels.ending: self._robot_check_events(command) self._update_audio1() self._update_particles() self._add_gravity() self._move() self._check_collisions() self._update_vectors() self._update_sprites() self._update_audio2() self._check_level() self._update_timer() self._update_stats() else: self._creative() self._check_level() self._update_sprites() def _robot_check_events(self, command): if command: if command == "Crouch": self.jumpCount += 1 self.isCrouch = True elif command == "Jump": self._jump("up") elif command == "Freeze": self.angle, self.speed = 0, 0 self.angle, self.speed = self.physics.add_vectors(self.angle, self.speed, -self.physics.gravity[0], -self.physics.gravity[1]) elif command == "WalkLeft": self._walk("left") elif command == "WalkRight": self._walk("right") elif command == "JumpRight": self._jump("right") else: self.isWalk = False def _check_events(self, agentCommand=None): if agentCommand is not None: keys = get_action_dict(agentCommand) else: keys = pygame.key.get_pressed() if not self.isSplat or self.splatCount > self.splatDuration: if keys[pygame.K_SPACE]: self.splatCount = 0 self.idle_counter = 0 self.jumpCount += 1 if not self.isCrouch: self.isCrouch = True elif self.jumpCount > self.maxJumpCount: if keys[pygame.K_RIGHT]: self._jump("right") elif keys[pygame.K_LEFT]: self._jump("left") else: self._jump("up") else: if keys[pygame.K_RIGHT]: self.splatCount = 0 self.idle_counter = 0 # Walk if not self.isCrouch: self._walk("right") # Jump else: self._jump("right") elif keys[pygame.K_LEFT]: self.splatCount = 0 self.idle_counter = 0 #Walk if not self.isCrouch: self._walk("left") #Jump else: self._jump("left") else: self.idle_counter += 1 self.isWalk = False if self.isCrouch: self._jump("up") else: self.splatCount += 1 def _add_gravity(self): self.angle, self.speed = self.physics.add_vectors(self.angle, self.speed, self.physics.gravity[0], self.physics.gravity[1]) def _move(self): if self.speed > self.maxSpeed: self.speed = self.maxSpeed x, y = self.rect_x, self.rect_y self.rect_x += math.sin(self.angle) * self.speed self.rect_y -= math.cos(self.angle) * self.speed #self.rect.move_ip(round(math.sin(self.angle) * self.speed), round(-math.cos(self.angle) * self.speed)) if self.rect_x != x or abs(self.rect_y - y) > 1: self.idle_counter = 0 self.isLookUp = False self.isDance = False self.danceCount = 0 def _collide_right(self, platform): rect = self.rect if ( self.rect_x + self.rect_width > platform.rect.left > self.rect_x and (platform.rect.top < rect.y < platform.rect.bottom or platform.rect.top < rect.y + rect.height < platform.rect.bottom or rect.y < platform.rect.top < rect.y + rect.height or rect.y < platform.rect.bottom < rect.y + rect.height) and round(rect.x + rect.width - platform.rect.left, 4) <= math.ceil(math.sin(self.angle) * self.speed) #and round(math.sin(self.angle), 4) > 0 ): return True else: return False def _collide_left(self, platform): rect = self.rect if ( self.rect_x < platform.rect.right < self.rect_x + self.rect_width and (platform.rect.top < rect.y < platform.rect.bottom or platform.rect.top < rect.y + rect.height < platform.rect.bottom or rect.y < platform.rect.top < rect.y + rect.height or rect.y < platform.rect.bottom < rect.y + rect.height) and round(rect.x - platform.rect.right, 4) >= math.floor(math.sin(self.angle) * self.speed) #and round(math.sin(self.angle), 4) < 0 ): return True else: return False def _collide_top(self, platform): if ( self.rect_y < platform.rect.bottom < self.rect_y + self.rect_height and (platform.rect.left < self.rect_x < platform.rect.right or platform.rect.left < self.rect_x + self.rect_width < platform.rect.right or self.rect_x < platform.rect.left < self.rect_x + self.rect_width or self.rect_x < platform.rect.right < self.rect_x + self.rect_width) and round(self.rect_y - platform.rect.bottom, 4) >= math.floor(-math.cos(self.angle) * self.speed) #and round(-math.cos(self.angle), 4) < 0 ): return True else: return False def _collide_bottom(self, platform): if ( self.rect_y + self.rect_height > platform.rect.top > self.rect_y and (platform.rect.left < self.rect_x < platform.rect.right or platform.rect.left < self.rect_x + self.rect_width < platform.rect.right or self.rect_x < platform.rect.left < self.rect_x + self.rect_width or self.rect_x < platform.rect.right < self.rect_x + self.rect_width) and round(self.rect_y + self.rect_height - platform.rect.top, 4) <= math.ceil(-math.cos(self.angle) * self.speed) #and round(-math.cos(self.angle), 4) > 0 ): return True else: return False def _collide_slope_bottom(self, platform, rel_x): if rel_x > platform.rect.width: rel_x = platform.rect.width rel_y = platform.rect.bottom - (platform.rect.bottom - platform.rect.top)/(platform.rect.right - platform.rect.left)*(rel_x) if ( self.rect_y + self.rect_height > rel_y > self.rect_y and (platform.rect.left < self.rect_x < platform.rect.right or platform.rect.left < self.rect_x + self.rect_width < platform.rect.right or self.rect_x < platform.rect.left < self.rect_x + self.rect_width or self.rect_x < platform.rect.right < self.rect_x + self.rect_width) ): return True else: return False def _collide_slope_top(self, platform, rel_x): if rel_x > platform.rect.width: rel_x = platform.rect.width rel_y = platform.rect.top + (platform.rect.bottom - platform.rect.top)/(platform.rect.right - platform.rect.left)*(rel_x) if ( self.rect_y < rel_y < self.rect_y + self.rect_height and (platform.rect.left < self.rect_x < platform.rect.right or platform.rect.left < self.rect_x + self.rect_width < platform.rect.right or self.rect_x < platform.rect.left < self.rect_x + self.rect_width or self.rect_x < platform.rect.right < self.rect_x + self.rect_width) ): return True else: return False def _check_collisions(self): self.isFalling = True self.collideTop = False self.collideRight = False self.collideLeft = False self.collideBottom = False self.collideRamp = False self.slip = 0 self.slope = 0 for platform in self.levels.levels[self.levels.current_level].platforms: if not platform.slope: if self._collide_left(platform): self.rect_x = platform.rect.right self.lastCollision = platform self.collided = True self.collideRight = True elif self._collide_right(platform): self.rect_x = platform.rect.left - self.rect_width self.lastCollision = platform self.collided = True self.collideLeft = True elif self._collide_top(platform): self.rect_y = platform.rect.bottom self.lastCollision = platform self.collideTop = True elif self._collide_bottom(platform): self.slip = platform.slip self.rect_y = platform.rect.top - self.rect_height self.isFalling = False self.collided = False self.isContact = False self.collideBottom = True if not self.lastCollision: self.isLanded = True if self.speed >= self.maxSpeed: self.isSplat = True self.isWalk = False self.isJump = False self.isDance = False self.falls += 1 self.lastCollision = platform self.level_change = 0 if platform.slope: if platform.slope[1] > 0: if platform.slope[0] > 0: rel_x = self.rect_x + self.rect_width - platform.rect.left if self._collide_left(platform): self.rect_x = platform.rect.right self.lastCollision = platform self.collided = True self.collideRight = True elif self._collide_right(platform) and self.rect_y + self.rect_height > platform.rect.bottom: self.rect_x = platform.rect.left - self.rect_width self.lastCollision = platform self.collided = True self.collideLeft = True elif self._collide_top(platform): self.rect_y = platform.rect.bottom self.lastCollision = platform self.collideTop = True elif self._collide_slope_bottom(platform, rel_x): # if self.rect_x + self.rect_width < platform.right: while self._collide_slope_bottom(platform, rel_x): if self.isFalling: self.rect_y -= 1 self.rect_x -= 1 else: self.rect_x -= 1 rel_x = self.rect_x + self.rect_width - platform.rect.left #else: # self.rect_y = platform.top - self.rect_height self.lastCollision = platform self.collideRamp = True self.slope = platform.slope[0] self.slip = platform.slip if platform.slope[0] < 0: rel_x = platform.rect.right - self.rect_x if self._collide_right(platform): self.rect_x = platform.rect.left - self.rect_width self.lastCollision = platform self.collided = True self.collideLeft = True elif self._collide_left(platform) and self.rect_y + self.rect_height > platform.rect.bottom: self.rect_x = platform.rect.right self.lastCollision = platform self.collided = True self.collideRight = True elif self._collide_top(platform): self.rect_y = platform.bottom self.lastCollision = platform self.collideTop = True elif self._collide_slope_bottom(platform, rel_x): # if self.rect_x > platform.left: while self._collide_slope_bottom(platform, rel_x): if self.isFalling: self.rect_x += 1 self.rect_y -= 1 else: self.rect_x += 1 rel_x = platform.rect.right - self.rect_x #else: # self.rect_y = platform.top - self.rect_height self.lastCollision = platform self.collideRamp = True self.slope = platform.slope[0] self.slip = platform.slip if platform.slope[1] < 0: if platform.slope[0] < 0: rel_x = self.rect_x + self.rect_width - platform.rect.left if self._collide_left(platform): self.rect_x = platform.rect.right self.lastCollision = platform self.collided = True self.collideRight = True elif self._collide_right(platform) and self.rect_y < platform.rect.top: self.rect_x = platform.rect.left - self.rect_width self.lastCollision = platform self.collided = True self.collideLeft = True elif self._collide_bottom(platform): self.rect_y = platform.rect.bottom self.lastCollision = platform self.collideTop = True elif self._collide_slope_top(platform, rel_x): while self._collide_slope_top(platform, rel_x): self.rect_x -= 1 rel_x = self.rect_x + self.rect_width - platform.rect.left # else: # self.rect_y = platform.top - self.rect_height self.collided = True self.collideTop = True self.lastCollision = platform if platform.slope[0] > 0: rel_x = platform.rect.right - self.rect_x if self._collide_right(platform): self.rect_x = platform.rect.left - self.rect_width self.lastCollision = platform self.collided = True self.collideLeft = True elif self._collide_left(platform) and self.rect_y < platform.rect.top: self.rect_x = platform.rect.right self.lastCollision = platform self.collided = True self.collideRight = True elif self._collide_bottom(platform): self.rect_y = platform.rect.bottom self.lastCollision = platform self.collideTop = True elif self._collide_slope_top(platform, rel_x): while self._collide_slope_top(platform, rel_x): self.rect_x += 1 rel_x = platform.rect.right - self.rect_x # else: # self.rect_y = platform.top - self.rect_height self.collided = True self.collideTop = True self.lastCollision = platform #Hits The Sides if self.rect_x + self.rect_width > self.screen.get_width(): self.rect_x = self.screen.get_width() - self.rect_width self.collideRight = True self.collided = True if self.rect_x < 0: self.rect_x = 0 self.collideLeft = True self.collided = True if not any([self.collideTop, self.collideRight, self.collideLeft, self.collideBottom, self.collideRamp]): self.lastCollision = None def _update_vectors(self): if self.collideRamp and not self.collideBottom: if math.cos(self.angle) * self.slope > 0: if self.slope < 0: self.angle = 3 * math.pi / 4 else: self.angle = math.pi / 4 else: if self.slope < 0: self.angle = 7 * math.pi / 4 else: self.angle = 5 * math.pi / 4 self.angle, self.speed = self.physics.add_vectors(self.angle, self.speed, 7 * math.pi / 4 * self.slope, self.physics.gravity[1]) self.angle, self.speed = self.physics.add_vectors(self.angle, self.speed, 5 * math.pi / 4 * self.slope, self.physics.gravity[1]) if not self.slip: self.speed -= 0.35 else: self.speed -= 0.10 if self.speed > self.maxSlopeSpeed: self.speed = self.maxSlopeSpeed if self.isFalling: if self.collideTop: self.angle = math.pi - self.angle self.speed *= self.elasticity/2 if self.collideRight or self.collideLeft: if round(-math.cos(self.angle), 4) <= 0: self.angle = -self.angle * self.angle_elasticity elif round(-math.cos(self.angle), 4) > 0: self.angle = math.pi + (math.pi - self.angle) * self.angle_elasticity self.speed *= self.elasticity self.isCrouch = False if self.collideBottom: self.angle, self.speed = self.physics.add_vectors(self.angle, self.speed, -self.physics.gravity[0], -self.physics.gravity[1]) self.speed *= self.slip def _check_level(self): if self.rect_y < 0 and self.levels.current_level < self.levels.max_level: self.rect_y += self.screen.get_height() + self.rect_width self.levels.current_level += 1 self.level_change += 1 if self.rect_y > self.screen.get_height(): self.rect_y -= self.screen.get_height() + self.rect_width self.levels.current_level -= 1 self.level_change -= 1 def _walk(self, direction): if self.lastCollision: if not self.lastCollision.snow: self.speed = self.walkSpeed self.angle = self.walkAngles[direction] self.isWalk = True self.isSplat = False self.direction = direction def _jump(self, direction): speed = (1.5 + ((self.jumpCount/5)**1.13)) if direction == "up": angle = 0 else: angle = self.jumpAngles[direction] * (1 - self.jumpCount / 45.5) speed += 0.9 if direction != "up": self.direction = direction if self.lastCollision.snow: if speed > 2.5: self.angle, self.speed = self.physics.add_vectors(self.angle, self.speed, angle, speed) else: self.angle, self.speed = self.physics.add_vectors(self.angle, self.speed, angle, speed) self.isSplat = False self.isJump = True self.isCrouch = False self.isWalk = False self.jumpCount = 0 self.jumps += 1 def _creative(self): keys = pygame.key.get_pressed() if keys[pygame.K_UP]: self.rect_y -= self.creative_speed if keys[pygame.K_DOWN]: self.rect_y += self.creative_speed if keys[pygame.K_RIGHT]: self.rect_x += self.creative_speed if keys[pygame.K_LEFT]: self.rect_x -= self.creative_speed def _update_sprites(self): if self.isWalk: if self.walkCount <= 5: if not self.isHoldingBabe: self.current_image = self.sprites[self.direction]["King_Walk1"] else: self.current_image = self.sprites["ending"][f"King_Walk1_{self.direction}"] elif self.walkCount <= 8: if not self.isHoldingBabe: self.current_image = self.sprites[self.direction]["King_MidWalk"] else: self.current_image = self.sprites["ending"][f"King_MidWalk_{self.direction}"] elif self.walkCount <= 13: if not self.isHoldingBabe: self.current_image = self.sprites[self.direction]["King_Walk2"] else: self.current_image = self.sprites["ending"][f"King_Walk2_{self.direction}"] elif self.walkCount <= 18: if not self.isHoldingBabe: self.current_image = self.sprites[self.direction]["King_MidWalk"] else: self.current_image = self.sprites["ending"][f"King_MidWalk_{self.direction}"] else: self.walkCount = 0 self.walkCount += 1 else: if self.isSplat: self.current_image = self.sprites[self.direction]["King_Fell"] elif self.isSnatch: self.current_image = self.sprites["ending"]["King_Snatch"] elif self.isDance: if self.danceCount <= 16: self.current_image = self.sprites[self.direction]["King_Dance_1"] elif self.danceCount <= 32: self.current_image = self.sprites[self.direction]["King_Dance_2"] elif self.danceCount <= 48: self.current_image = self.sprites[self.direction]["King_Dance_3"] elif self.danceCount <= 64: self.current_image = self.sprites[self.direction]["King_Dance_2"] else: self.danceCount = 0 self.danceCount += 1 if (self.idle_counter - self.idle_time) % self.idle_length == 0: self.isDance = False elif self.isLookUp: self.current_image = self.sprites[self.direction]["King_Look_Up"] if (self.idle_counter - self.idle_time) % self.idle_length == 0: self.isLookUp = False elif self.idle_counter > self.idle_time and (self.idle_counter - self.idle_time) % self.idle_length == 0: x = random.randint(0, 2) if x == 0: self.isDance = True elif x == 1: self.isLookUp = True else: pass else: if self.isHoldingBabe: self.current_image = self.sprites["ending"][f"King_Hold_Babe_{self.direction}"] elif self.isSnatch: self.current_image = self.sprites["ending"]["King_Snatch"] elif self.isHoldingUpHands: self.current_image = self.sprites["ending"]["King_Hold_Up_Hands"] elif self.isWearingCrown: self.current_image = self.sprites["ending"]["King_Standing"] else: self.current_image = self.sprites[self.direction]["King_Standing"] self.walkCount = 0 if self.isCrouch: if not self.isHoldingBabe: self.current_image = self.sprites[self.direction]["King_Crouch"] else: self.current_image = self.sprites["ending"]["King_Hold_Babe_Crouch"] if self.isFalling: if not self.collided: if self.angle <= math.pi/2 or self.angle >= 3 * math.pi / 2: if self.isHoldingBabe: self.current_image = self.sprites["ending"]["King_Umbrella1"] elif self.isWearingCrown: self.current_image = self.sprites["ending"]["King_Jump"] else: self.current_image = self.sprites[self.direction]["King_Jump"] else: if self.isHoldingBabe: if self.speed == self.maxSpeed: if self.umbrellaCount > 28: self.umbrellaCount = 11 if self.umbrellaCount <= 10: self.current_image = self.sprites["ending"]["King_Umbrella0"] elif self.umbrellaCount <= 16: if self.isAdmiring: self.current_image = self.sprites["ending"]["King_Look_Up_Umbrella1"] else: self.current_image = self.sprites["ending"]["King_Normal_Umbrella1"] elif self.umbrellaCount <= 22: if self.isAdmiring: self.current_image = self.sprites["ending"]["King_Look_Up_Umbrella2"] else: self.current_image = self.sprites["ending"]["King_Normal_Umbrella2"] elif self.umbrellaCount <= 28: if self.isAdmiring: self.current_image = self.sprites["ending"]["King_Look_Up_Umbrella3"] else: self.current_image = self.sprites["ending"]["King_Normal_Umbrella3"] self.umbrellaCount += 1 else: self.current_image = self.sprites["ending"]["King_Umbrella1"] elif self.isWearingCrown: self.current_image = self.sprites["ending"]["King_JumpFall"] else: self.current_image = self.sprites[self.direction]["King_JumpFall"] else: self.current_image = self.sprites[self.direction]["King_CollisionFall"] def _update_audio1(self): if self.lastCollision: if self.isJump: self.channel.play(self.audio[self.lastCollision.type]["king_jump"]) def _update_audio2(self): if self.lastCollision: if self.isFalling: if any([self.collideTop, self.collideLeft, self.collideRight]) and not self.isWalk: self.channel.play(self.audio[self.lastCollision.type]["king_bump"]) if self.isLanded and not self.isSplat: self.channel.play(self.audio[self.lastCollision.type]["king_land"]) elif self.isLanded and self.isSplat: self.channel.play(self.audio[self.lastCollision.type]["king_splat"]) def _update_particles(self): if self.isJump: self.jump_particle.play((self.x, self.y, self.width, self.height)) self.isJump = False if self.isLanded: if self.lastCollision.type == "Snow": self.snow_jump_particle.play((self.x, self.y, self.width, self.height)) self.isLanded = False def _update_timer(self): if not self.timer.start_time: self.timer.start() self.time += self.timer.elapsed_time() def _update_stats(self): os.environ["TIME"] = str(self.time) os.environ["JUMPS"] = str(self.jumps) os.environ["FALLS"] = str(self.falls) def reset(self,x,y,direction): self.isWalk = False self.isCrouch = False self.isFalling = False self.isContact = False # self.isSplat = True self.isSplat = False self.isDance = False self.isLookUp = False self.isSnatch = False self.isHoldingUpHands = False self.isHoldingBabe = False self.isAdmiring = False self.isWearingCrown = False self.collided = False self.jumpParticle = False self.lastCollision = None self.collideTop = False self.collideRight = False self.collideLeft = False self.collideBottom = False self.collideRamp = False self.isJump = False self.isLanded = False # Stats self.time = 0 self.jumps = 0 self.falls = 0 # Animation self.x, self.y = x, y self.width, self.height = 32, 32 self.rect_x, self.rect_y = self.x + 1, self.y + 7 self.rect_width, self.rect_height = self.width - 12, self.height - 8 self.direction = direction self.danceCount = 0 self.walkCount = 0 self.jumpCount = 0 self.umbrellaCount = 0 self.idle_counter = 0 self.speed, self.angle = 0, 0 self._update_sprites()
class Babe(King): def __init__(self, screen, levels): self.screen = screen self.sprites = Babe_Sprites().babe_images self.levels = levels self.level = self.levels.max_level self.timer = Timer() # Booleans self.isWalk = False self.isCrouch = False self.isFalling = False self.isKiss = False self.hasKissed = False self.collideBottom = False self.lastCollision = True # Animation self.walkCount = 0 self.x, self.y = 375, 113 self.width, self.height = 32, 32 self.rect_x, self.rect_y = self.x + 1, self.y + 7 self.rect_width, self.rect_height = self.width - 12, self.height - 8 self.current_image = self.sprites["Babe_Stand1"] # Particles self.jump_particle = King_Particle("images\\particles\\jump_particle.png", 5, 1, 32) self.snow_jump_particle = King_Particle("images\\particles\\snow_jump_particle.png", 4, 3, 36) self.isJump = False self.isLanded = False # Audio self.channel = pygame.mixer.Channel(10) self.audio = Babe_Audio().audio # Physics self.physics = Physics() self.speed, self.angle = 0, 0 self.maxSpeed = 11 self.walkAngles = {"right" : math.pi/2, "left" : -math.pi/2} self.slip = 0 # Ending self.ending_distance = 50 def blitme(self): self.x = self.rect.x - 6 self.y = self.rect.y - 9 if self.levels.current_level == self.level: self.screen.blit(self.current_image, (self.x, self.y)) # pygame.draw.rect(self.screen, (255, 0, 0), self.rect, 1) def update(self, king, command = None): if self.levels.current_level == self.level: self._check_events(command) self._update_audio1() self._add_gravity() self._move() self._check_collisions() self._update_vectors() self._update_sprites() self._update_audio2() self._update_particles() if not self.levels.ending: self._check_ending(king) def _check_ending(self, king): if self.rect_y - king.rect_y >= 0: if self.rect_x - king.rect_x <= self.ending_distance: self.levels.ending = True king.rect_x, king.rect_y = self.rect_x - self.ending_distance, self.rect_y king.speed = 0 def _check_events(self, command): if command: if command == "Crouch" and not self.isCrouch: self.timer.start() self.isCrouch = True elif command == "Jump": self._jump() elif command == "Kiss": self.isKiss = True elif command == "WalkLeft": self._walk("left") elif command == "WalkRight": self._walk("right") elif command == "Snatched": self.rect_y += 999 else: self.isKiss = False self.hasKissed = False def _move(self): if self.speed > self.maxSpeed: self.speed = self.maxSpeed self.rect_x += math.sin(self.angle) * self.speed self.rect_y -= math.cos(self.angle) * self.speed # def _check_collisions(self): # self.isFalling = True # self.collideBottom = False # self.slip = 0 # for platform in self.levels.levels[self.levels.current_level].platforms: # if self._collide_rect(self.rect, platform): # if self.rect.bottom >= platform.top and round(self.rect.bottom - platform.top) <= round(self.speed) and -math.cos(self.angle) > 0 and not platform.support: # self.rect.bottom = platform.top # self.isFalling = False # self.isContact = False # self.collideBottom = True # if not self.lastCollision: # self.isLanded = True # self.lastCollision = platform # self.slip = platform.slip # if not self.collideBottom: # self.lastCollision = None def _update_vectors(self): if self.collideBottom: self.angle, self.speed = self.physics.add_vectors(self.angle, self.speed, -self.physics.gravity[0], -self.physics.gravity[1]) self.speed *= self.slip def _walk(self, direction): self.speed = 1 self.angle = self.walkAngles[direction] self.isWalk = True def _jump(self): speed = (2 + (self.timer.elapsed_time()*2) / 150) angle = 0 self.angle, self.speed = self.physics.add_vectors(self.angle, self.speed, angle, speed) self.isJump = True self.isCrouch = False self.isWalk = False self.timer.end() def _update_sprites(self): if self.isCrouch: self.current_image = self.sprites["Babe_Crouch"] if self.isFalling: if self.angle < math.pi/2 or self.angle > 3 * math.pi / 2: self.current_image = self.sprites["Babe_Jump"] else: self.current_image = self.sprites["Babe_Fall"] elif self.isKiss: self.current_image = self.sprites["Babe_Kiss"] elif self.lastCollision and self.isLanded: self.current_image = self.sprites["Babe_Land"] else: if self.walkCount <= 5: self.current_image = self.sprites["Babe_Stand1"] elif self.walkCount <= 8: self.current_image = self.sprites["Babe_Stand2"] elif self.walkCount <= 13: self.current_image = self.sprites["Babe_Stand3"] else: self.walkCount = 0 self.walkCount += 1 def _update_audio1(self): if self.lastCollision: if self.isJump: self.channel.play(self.audio["babe_jump"]) def _update_audio2(self): if self.lastCollision: if self.isLanded: self.channel.play(self.audio["king_land"]) self.isLanded = False if self.isKiss: if not self.channel.get_busy() and not self.hasKissed: self.channel.play(self.audio["babe_kiss"]) self.hasKissed = True
class fakeDAQ: """ DAQ""" def __init__(self, params): try: self.rawdata = params['rawdata'] self.scan_rate = params['scan_rate'] self.acq_dur = params['acq_dur'] # acquistion segment duration except KeyError: raise self.ch = list(range(0,self.rawdata.shape[1])) self.read_request_size =int(self.scan_rate*self.acq_dur) self.data =[] # segment data self.t =[] # acquisition relative time for segment self.acq_counter = 0 # segment counter self.total_nsample_perchannel =0 # total number of samples per channel if 'timer' in params: self.timer = params['timer'] else: self.timer = Timer() self.data_acqtime ={} #relative time of data-segment acquisition self.data_len = {} # sample number per each segment self.worker = Threadworker(self.acq_start) def reset_timer(self): """ def reset_timer(self): reset timer """ self.timer.start() def record_cont(self): """ def record_cont(self): recording continously while scan_status is running """ nsample = int(self.scan_rate*self.acq_dur) nch = len(self.ch) datalen = self.rawdata.shape[0] while self.worker.running() : try: sleep(self.acq_dur) #sleep(0.001) if self.total_nsample_perchannel>datalen: break self.data_acqtime[self.acq_counter] = self.timer.elapsed_time() inx = range(self.acq_counter*nsample,(self.acq_counter+1)*nsample) self.data = self.rawdata[inx,:] timeoff = self.total_nsample_perchannel/self.scan_rate self.t = timeoff + np.array(range(0,nsample))/self.scan_rate self.data_len[self.acq_counter] =nsample workername = 'fakeDAQ' #logging.debug('{}: counter:{}, nsample:{}, abstime:{}'.format(workername,self.acq_counter, self.total_nsample_perchannel, self.data_acqtime[self.acq_counter])) self.worker.set_datflag() self.total_nsample_perchannel += nsample self.acq_counter +=1 except KeyboardInterrupt: logging.info('\nExit from DAQ\n') break self.acq_stop() def acq_start(self): """ def acq_start(self): acqusition start """ self.record_cont() self.worker.clear_datflag() def acq_stop(self): self.worker.stop()
class usb6009(DAQ): """ NI USB-6009 DAQ: for analog input and output""" def __init__(self, params): #super(usb6009, self).__init__(params) # for python 2.7 DAQ.__init__(self, params) self.device_name = 'USB-6009' try: self.dev_id = params['dev_id'] self.ai_fdb_chan = params['ai_feedback_ch'] if self.mode == 'trigger': self.trg_chan = params['ai_trg_ch'] self.trg_mode = params[ 'trg_mode'] #'rising_edge' or 'falling_edge' self.ao_chan = params['ao_ch'] self.acq_dur = params['acq_dur'] self.ai_buffersize = 5100 self.timeout = 10 except (KeyError, ValueError) as err: logging.error(err, exc_info=True) if 'timer' in params: self.timer = params['timer'] else: self.timer = Timer() self.init_daq() self.aiworker = Threadworker(self.acq_start) self.aiworker.setName('DAQthreader_ch' + str(self.ai_ch)) self.aiworker_live = True def init_daq(self): """ configure USB-6009""" system = nidaqmx.system.System.local() dev = system.devices[self.dev_id] #dev = system.devices['Dev3'] try: if not (dev.product_type == self.device_name): logging.error('not proper DAQ{} selected!\n', dev.product_type) self.task_ao = nidaqmx.Task() self.task_ai = nidaqmx.Task() ao_ch = self.get_channame('ao', self.ao_chan) self.task_ao.ao_channels.add_ao_voltage_chan(ao_ch, min_val=0.0, max_val=5.0) for i in self.ai_ch: ai_ch = self.get_channame('ai', i) self.task_ai.ai_channels.add_ai_voltage_chan(ai_ch) #ai_ch = self.get_channame('ai', self.ai_fdb_chan) #self.task_ai.ai_channels.add_ai_voltage_chan(ai_ch) #trg_ch = self.get_channame('ai', self.trg_chan) #self.task_ai.ai_channels.add_ai_voltage_chan(trg_ch) self.task_ai.timing.cfg_samp_clk_timing(self.scan_rate,samps_per_chan=self.ai_buffersize, \ sample_mode= nidaqmx.constants.AcquisitionType.CONTINUOUS) self.scan_rate = self.task_ai.timing.samp_clk_rate # actual sample rate set in the USB-6009 self.read_request_size = int( self.scan_rate * self.acq_dur) # requested sample number except (nidaqmx.errors.DaqError, KeyError, ValueError) as err: logging.error(err, exc_info=True) def get_channame(self, chtype, ch): """ def get_channame(self, chtype,ch): chtype: 'ao', 'ai' ch: channel number return device dependent channel names """ return self.dev_id + "/" + chtype + str(ch) def get_ai_ch_inx(self, ch): """ def get_ai_ch_inx(self,chtype, ch): """ chname = self.get_channame('ai', ch) chs = self.task_ai.channel_names return chs.index(chname) def record_N_sample(self): """ def record_N_sample(self): read definite N samples """ #self.total_samples_read =0 self.acq_counter = 0 segment_size = nidaqmx.constants.READ_ALL_AVAILABLE #set segment size to 100msec N = self.read_request_size segdur = 1 #self.ai_buffersize/self.scan_rate while self.total_nsample_perchannel < N: if not self.aiworker.running(): break data = self.task_ai.read(segment_size, self.timeout) self.data_acqtime[self.acq_counter] = self.timer.elapsed_time() nsample = len(data[0]) # dataseg = np.array(data) timeoff = self.total_nsample_perchannel / self.scan_rate tseg = timeoff + np.array(range(0, nsample)) / self.scan_rate if self.acq_counter == 0: self.data = dataseg self.t = tseg else: self.data = np.hstack((self.data, dataseg)) self.t = np.hstack((self.t, tseg)) self.data_len[self.acq_counter] = nsample workername = self.aiworker.getName() logging.debug('{}: counter:{}, nsample:{}, abstime:{}'.format( workername, self.acq_counter, nsample, self.data_acqtime[self.acq_counter])) self.total_nsample_perchannel += nsample self.acq_counter += 1 sleep(segdur * 0.95) def wait_for_trigger(self): """ def wait_for_trigger(self): wait_for_trigger """ inxch = self.get_ai_ch_inx(self.trg_chan) while True: value = self.task_ai.read() if self.trg_mode == 'rising_edge' and np.mean(value[inxch]) > 2.5: logging.info('Triggered') break elif self.trg_mode == 'falling_edge' and np.mean( value[inxch]) < 2.5: logging.info('Triggered') break sleep(0.001) def write_volt(self, vals): """ def write_volt(self, val): vals: list for multiple channels """ nch = len(self.task_ao.channel_names) if nch == len(vals): self.task_ao.write(vals) else: logging.error('No. ch:{}, No. val:{}'.format(nch, len(vals))) def acq_start(self): """ def acq_start(self): acqusition start, this function is called from thread.start() within this function, record_X should be called """ while True: if not self.aiworker_live: break if self.aiworker.running(): if self.mode == 'trigger': self.wait_for_trigger() self.task_ai.start() self.record_N_sample() sleep(0.1) def acq_resume(self): """ def acq_resume(self): start ai acquistion """ # if thread was not started if not self.aiworker.is_alive(): self.aiworker.start() logging.info("aiworker is started") # if thread was started already if not self.aiworker.running(): self.aiworker.resume() logging.info("aiworker resumes working") def acq_stop(self): """ def acq_stop(self): acqusition stop """ self.task_ai.stop() self.task_ao.stop() self.aiworker.stop() def cleanup(self): self.aiworker.stop() self.aiworker_live = False
class MCC118(DAQ): """ mcc118""" def __init__(self, params): #super(DAQ,self).__init__(params) super().__init__(params) try: self.timeout = params['timeout'] self.acq_dur = params['acq_dur'] # acquistion segment duration except KeyError: raise if 'timer' in params: self.timer = params['timer'] else: self.timer = Timer() self.read_request_size =[] # will be converted from self.acq_dur from init_daq self.hat = [] if 'save_dir' in params.keys(): self.fn = get_fn(params['save_dir']) else: self.fn = None self.init_daq() #self.worker = Threadworker(self.record) #self.worker.setName('DAQthreader_ch'+str(self.ai_ch)) #self.worker.setName('DAQthreader_ch'+str(self.ai_ch)) #manager = mp.Manager() #self.data = manager.list() #self.t = manager.list() #self.worker = pw.Processworker(target=self.record, args=(self.data,self.t)) self.worker = pw.Processworker(target=self.record, args=tuple()) def init_daq(self): try: address = select_hat_device(HatIDs.MCC_118) self.hat = mcc118(address) num_channels = len(self.ai_ch) self.scan_rate = self.hat.a_in_scan_actual_rate(num_channels, self.scan_rate) self.read_request_size = int(self.scan_rate*self.acq_dur) except (NameError, SyntaxError): pass def reset_timer(self): """ def reset_timer(self): reset timer """ self.timer.start() #def record_cont(self,data,t): def record_cont(self): """ def record_cont(self): recording continously while scan_status is running """ nch = len(self.ai_ch) #self.reset_timer() scan_status = self.hat.a_in_scan_status() while self.worker.running() & scan_status.running : scan_status = self.hat.a_in_scan_status() nsample =scan_status.samples_available if nsample>= self.read_request_size: read_result = self.hat.a_in_scan_read_numpy(READ_ALL_AVAILABLE, self.timeout) D= read_result.data.astype(DTYPE) elapsed_time = self.timer.elapsed_time() self.data_acqtime[self.acq_counter] = elapsed_time logging.debug(scan_status) nsample = int(len(read_result.data) / nch) # self.data_len[self.acq_counter] =nsample # Check for an overrun error if read_result.hardware_overrun: logging.error('\n\nHardware overrun\n') elif read_result.buffer_overrun: logging.error('\n\nBuffer overrun\n') if self.fn: dseg = np.reshape(D,(nsample,nch)) timeoff = self.total_nsample_perchannel/self.scan_rate tseg = timeoff + np.array(range(0,nsample), dtype=DTYPE)/self.scan_rate tseg = tseg[:,np.newaxis] data = np.concatenate((tseg,dseg), axis=1) with open(self.fn,'ab') as file: file.write(data) logging.debug('\n===================\n') logging.debug('file name:{}, segment:{} saved'.format(self.fn, self.acq_counter)) logging.debug('\n===================\n') #data.append(np.reshape(D,(nsample,nch))) #t.append(timeoff + np.array(range(0,nsample), dtype='float32')/self.scan_rate) self.worker.set_datflag() self.total_nsample_perchannel += nsample self.acq_counter +=1 sleep(self.acq_dur*0.9) else: sleep(0.05) print("\n===================\nRecording time: " + str(elapsed_time)+"\n") def record_N_sample(self): """ def record_N_sample(self): read N samples This version of the function is old version. TO DO: implement file saving """ nch = len(self.ai_ch) scan_status = self.hat.a_in_scan_status() total_samples_read =0 segment_size = int(self.scan_rate* 0.1) #set segment size to 100msec N = self.read_request_size if self.worker.running() & scan_status.running : while total_samples_read <N: read_result = self.hat.a_in_scan_read_numpy(segment_size, self.timeout) self.data_acqtime[self.acq_counter] = self.timer.elapsed_time() nsample = int(len(read_result.data) / nch) # # Check for an overrun error if read_result.hardware_overrun: logging.error('\n\nHardware overrun\n') elif read_result.buffer_overrun: logging.error('\n\nBuffer overrun\n') dataseg = np.reshape(read_result.data,(nsample,nch)) timeoff = self.total_nsample_perchannel/self.scan_rate tseg = timeoff + np.array(range(0,nsample))/self.scan_rate t = np.hstack((t,tseg)) data = np.vstack((data,dataseg)) self.data_len[self.acq_counter] =nsample #workername = self.worker.getName() #logging.debug('{}: counter:{}, nsample:{}, abstime:{}'.format(workername,self.acq_counter, nsample, self.data_acqtime[self.acq_counter])) self.total_nsample_perchannel += nsample self.acq_counter +=1 sleep(segment_size*0.9) self.worker.set_datflag() # set data_ready_flag def wait_for_trigger(self): """ Monitor the status of the specified HAT device in a loop until the triggered status is True or the running status is False. """ # Read the status only to determine when the trigger occurs. is_running = True is_triggered = False while is_running and not is_triggered: status = self.hat.a_in_scan_status() is_running = status.running is_triggered = status.triggered def record_withtrigger(self): while self.worker.running(): self.wait_for_trigger() self.record_N_sample() def record(self): """ def record(self): acqusition start """ channel_mask = chan_list_to_mask(self.ai_ch) if self.mode =='continuous': samples_per_channel = 0 options = OptionFlags.CONTINUOUS self.hat.a_in_scan_start(channel_mask, samples_per_channel, self.scan_rate,options) self.record_cont() elif self.mode=='trigger': samples_per_channel = self.read_request_size options = OptionFlags.EXTTRIGGER trigger_mode = TriggerModes.RISING_EDGE self.hat.trigger_mode(trigger_mode) self.hat.a_in_scan_start(channel_mask, samples_per_channel, self.scan_rate,options) self.record_withtrigger() elif self.mode =='finite': samples_per_channel = self.read_request_size options = OptionFlags.DEFAULT self.hat.a_in_scan_start(channel_mask, samples_per_channel, self.scan_rate,options) self.record_N_sample() else: logging.error('not implmented\n') raise self.worker.clear_datflag() def acq_start(self): self.worker.start_withflag() self.reset_timer() def acq_stop(self): self.worker.stop() sleep(0.1) self.hat.a_in_scan_stop() def acq_cleanup(self): self.hat.a_in_scan_cleanup()