Exemplo n.º 1
0
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
Exemplo n.º 2
0
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()
Exemplo n.º 3
0
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
Exemplo n.º 4
0
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()                
Exemplo n.º 5
0
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()
Exemplo n.º 6
0
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
Exemplo n.º 7
0
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()
Exemplo n.º 8
0
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
Exemplo n.º 9
0
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()