class Module(Thread): HEADER = '\033[95m' BLUE = '\033[94m' CYAN = '\033[36m' GREEN = '\033[92m' YELLOW = '\033[93m' FAIL = '\033[91m' ENDC = '\033[0m' BOLD = '\033[1m' UNDERLINE = '\033[4m' print_lock = Lock() def reset(self): return def __init__(self, next_module=None, **kwargs): Thread.__init__(self) self.output = next_module self.mutex = Lock() self.stop = False self.plt = None self.fig = 1 self.base = time() self.passthrough = False self.quitted = False # if main = True, then the thread will not start and be expected to be called from the # main thread self.main = False # TODO: legacy code that enabled calling matplotlib, needs to be replaced with Scope self.debug = False self.input = Queue() # Variable to update the ncurses interface to display zero data in queue self.zeroed = False # Scope represents our way of calling matplotlib # from the module. Since the module is on a separate # thread, scope is a queue mechanism to send data over # to the main thread. # A separate controller will manage calling the scope from # the main thread. self.scope = None # times is a dictionary to keep track of all the execution times of methods # and print it out in the end self.times = {} for key in kwargs: if key == 'fig': self.fig = int(kwargs[key]) elif key == 'passthrough': self.passthrough = bool(kwargs[key]) elif key == 'plt': self.plt = kwargs[key] elif key == 'main': self.main = bool(kwargs[key]) elif key == 'debug': self.debug = bool(kwargs[key]) elif key == 'scope_size': self.scope_size = int(kwargs[key]) if output_redirection: self.box = Box(0, 0, 0, 0) self.box_title = self.box.add_label(self.__class__.__name__) self.box_queue_size = self.box.add_label('0') self.box_queue_bar = self.box.add_bar(0) self.box_plot_on = self.box.add_label('plot: off') else: self.box = None def set_scope(self, scope): if scope is not None: self.box.notify(self.box_plot_on, 'plot: on') else: self.box.notify(self.box_plot_on, 'plot: off') self.mutex.acquire() self.scope = scope self.mutex.release() def num_scopes(self): return 1 def work(self): if not self.input.empty(): queue_size = len(self.input.queue) if self.box is not None: self.box.notify(self.box_queue_size, queue_size) self.box.notify(self.box_queue_bar, queue_size) self.zeroed = False in_data = self.input.get() if self.passthrough == True: self.output.input.put(in_data) return True start = time() out_dat = self.process(in_data) stop = time() #print self.YELLOW + self.__class__.__name__+':\t [%4.3f ms]'%(1000.0*(stop-start))+self.ENDC if self.output is not None: if out_dat is not None: self.output.input.put(out_dat) return True else: if self.box is not None and not self.zeroed: self.zeroed = True self.box.notify(self.box_queue_size, 0) self.box.notify(self.box_queue_bar, 0) return True def quit(self, all=False): # TODO: Quit gracefully self.print_times() self.mutex.acquire() self.stop = True self.mutex.release() if all and self.output != None: self.output.quit(True) if not self.main: self.join() def start(self): if self.box is not None: self.box_log = self.box.add_label('log:') if not self.main: Thread.start(self) if self.output != None: self.output.start() def run(self): Module.print_lock.acquire() self.log(self.__class__.__name__ + ' starting') Module.print_lock.release() base = time() try: while True: self.mutex.acquire() busy = self.work() self.mutex.release() if busy: base = time() else: if time() - base > 5.0: #sleep(0.5) pass self.mutex.acquire() if self.stop: self.mutex.release() break else: self.mutex.release() except Exception as e: Module.print_lock.acquire() self.log(self.FAIL + 'Exception in ' + self.__class__.__name__ + self.ENDC) traceback.print_exc() Module.print_lock.release() Module.print_lock.acquire() self.log(self.__class__.__name__ + ' quitting') self.quitted = True Module.print_lock.release() def process(self): return None def blog(self, msg): if self.box is not None: self.box.box_log(msg) def log(self, msg): if type(msg) != str: msg = str(msg) stdout.write(self.GREEN + self.__class__.__name__ + ':\t' + self.ENDC + msg + '\n') def print_kw_error(self, arg_name): msg = Module.FAIL + self.__class__.__name__ + ' requires key word argument %s!' % arg_name + Module.ENDC self.log(msg) self.box_log(msg) def print_pam(self, pam): msg = '\n' count = 0 byte = np.zeros(4) for p in pam: byte[count % 4] = p count += 1 if count % 4 == 0: msg += '%d: [%2d %2d %2d %2d]\n' % (count / 4, byte[0], byte[1], byte[2], byte[3]) if count % 4 > 0: msg += '%d: [' % (1 + count / 4) + ('%2d ' * (count % 4)) % tuple( byte[:count % 4]) + '...\n' self.log(msg) def start_timer(self, key): if self.times.has_key(key): self.times[key].append(time()) else: self.times[key] = [time()] def stop_timer(self, key): self.times[key][-1] = time() - self.times[key][-1] def print_times(self): msg = '\n' for key in self.times: msg += '%s, %.3f ms\n' % (key, 1000.0 * np.average(self.times[key])) self.log(msg) def cmd_info(self): msgs = [('pon', 'enable plot'), ('poff', 'disable plot'), ('q', 'quit the program')] return msgs def interpret_cmd(self, cmd): return