Exemple #1
0
class bciApp(bciCore):
    def __init__(self):
        super(bciApp, self).__init__(config_path=r'./config.js')

        self.PHASES = [{
            'name': 'start',
            'next': 'test',
            'duration': 1
        }, {
            'name': 'test',
            'next': 'relax',
            'duration': 5
        }, {
            'name': 'relax',
            'next': 'test',
            'duration': 3
        }, {
            'name': 'rrelax',
            'next': 'stop',
            'duration': 1
        }]

        self.CODER = DefaultCoder()

        layout = {
            'screen': {
                'size': (1000, 250),
                'color': (0, 0, 0),
                'type': 'normal',
                'Fps': 60,
                'caption': 'this is an example'
            },
            'ssvep1': {
                'class': 'sinBlock',
                'parm': {
                    'size': (150, 150),
                    'position': (125, 125),
                    'bordercolor': (0, 0, 0),
                    'anchor': 'center',
                    'frequency': 6,
                    'visible': True,
                    'start': False
                }
            },
            'ssvep2': {
                'class': 'sinBlock',
                'parm': {
                    'size': (150, 150),
                    'position': (375, 125),
                    'bordercolor': (0, 0, 0),
                    'anchor': 'center',
                    'frequency': 7,
                    'visible': True,
                    'start': False
                }
            },
            'ssvep3': {
                'class': 'sinBlock',
                'parm': {
                    'size': (150, 150),
                    'position': (625, 125),
                    'bordercolor': (0, 0, 0),
                    'anchor': 'center',
                    'frequency': 8,
                    'visible': True,
                    'start': False
                }
            },
            'ssvep4': {
                'class': 'sinBlock',
                'parm': {
                    'size': (150, 150),
                    'position': (875, 125),
                    'bordercolor': (0, 0, 0),
                    'anchor': 'center',
                    'frequency': 9,
                    'visible': True,
                    'start': False
                }
            },
        }

        self.gui = GuiIF(None, layout)
        _ = multiprocessing.Process(target=guiengine_proc,
                                    args=(self.gui.args, ))
        _.start()
        self.gui.wait()

        sp_ip = self.configs['signal_processing']['sp_host_ip']
        sp_port = self.configs['signal_processing']['sp_host_port']
        self.marker = Marker((sp_ip, sp_port))

        self.TEST_NUM = 80
        self.test_count = 1

    def transition(self, phase):
        write_log(phase)
        if phase == 'test':
            self.gui.update(
                {
                    'ssvep1': {
                        'start': True,
                        'bordercolor': (0, 0, 0)
                    },
                    'ssvep2': {
                        'start': True,
                        'bordercolor': (0, 0, 0)
                    },
                    'ssvep3': {
                        'start': True,
                        'bordercolor': (0, 0, 0)
                    },
                    'ssvep4': {
                        'start': True,
                        'bordercolor': (0, 0, 0)
                    }
                }, {})

            t = global_clock()
            print(t)
            self.marker.send_marker(
                {'process': {
                    'value': [1],
                    'timestamp': [t]
                }})  #开始测试

        elif phase == 'relax':
            self.gui.update(
                {
                    'ssvep1': {
                        'start': False
                    },
                    'ssvep2': {
                        'start': False
                    },
                    'ssvep3': {
                        'start': False
                    },
                    'ssvep4': {
                        'start': False
                    }
                }, {})

            self.marker.send_marker(
                {'process': {
                    'value': [2],
                    'timestamp': [global_clock()]
                }})  #测试完成

            self.test_count += 1
            if self.test_count > self.TEST_NUM:
                self.change_phase('rrelax')

    def stop_run(self):
        self.gui.quit()

    def process(self, result):
        if result is not None:
            print(result)
            mapp = {'6': 'ssvep1', '7': 'ssvep2', '8': 'ssvep3', '9': 'ssvep4'}
            self.gui.update({mapp[str(result)]: {
                                 'bordercolor': (255, 0, 0)
                             }}, {})
Exemple #2
0
class GuiEngine():
    stimuli = {}
    __release_ID_list = []

    def __init__(self, stims, Q_c2g, E_g2c, server_address):
        """
        stims:  dict to define a stimulus.
                eg. stims = {'cue':{'class':'Block','parm':{'size':(100,40),'position':(0,0)}}}
        Q_c2g: multiprocessing.Queue, used for accepting stimulus control command from core process
        kwargs: server_address = ?, the target server's address to accept marker
        
        property for describe screen
        size: (width,height)
        type: fullscreen/normal
        frameless: True/False
        color: (R,G,B)
        caption: string
        Fps: int, strongly suggest you set Fps as the same with system's Fps
        """

        self.Q_c2g = Q_c2g
        self.E_g2c = E_g2c
        self.marker_on = False
        self.marker_event = {}
        self.stp = False
        self.lock = threading.Lock()

        pygame.init()
        #初始化screen
        # 当且仅当window环境变量设置成功且fullscreen时,SCREEN_SYNC=True
        if stims['screen']['type'].lower() == 'fullscreen':
            self.screen = pygame.display.set_mode(
                (0, 0), FULLSCREEN | DOUBLEBUF | HWSURFACE, 32)
        else:
            # 将窗口置中
            if OS == 'windows':
                w, h = stims['screen']['size']
                x = int((SCRW - w) / 2.)
                y = int((SCRH - 50 - h) / 2.) - 50  # 扣除任务栏高度
                os.environ['SDL_VIDEO_WINDOW_POS'] = '%i,%i' % (x, y)

            self.screen = pygame.display.set_mode(stims['screen']['size'],
                                                  NOFRAME | DOUBLEBUF, 32)
            SCREEN_SYNC = False

        self.screen_color = stims['screen']['color']
        self.screen.fill(self.screen_color)
        pygame.display.set_caption(stims['screen']['caption'])
        self.Fps = stims['screen']['Fps']
        del stims['screen']

        self.ask_4_update_gui = False  #线程接收到刷新请求后,通知主进程刷新
        self.update_in_this_frame = False  #主进程在一帧真实的刷新帧中确定能够进行刷新
        self.__update_per_frame_list = []  #接受帧刷新对象

        if server_address is None:

            class Marker():
                def __init__(self, sa):
                    pass

                def send_marker(self, marker):
                    raise Exception(
                        'marker_sender was not initilized because server_address parameter was not given'
                    )

        self.marker_sender = Marker(server_address)

        #注册刺激,生成实例
        for ID in stims:
            element = stims[ID]
            clas = element['class']
            if clas in MODULES:
                self.stimuli[ID] = MODULES[clas](self.screen,
                                                 **element['parm'])

        backthread = threading.Thread(target=self.backthreadfun,
                                      args=(),
                                      daemon=True)
        backthread.start()

    def backthreadfun(self):  #接收刷新请求字典
        # arg = self.Q_c2g.get()
        # arg可能的形式:
        #     1. 单字符串:'_q_u_i_t_' -> 结束标志
        #     2. 列表:[stimulus setting, marker] -> 刺激设置,marker标志
        #     3. marker:  eg. {'mkr1':{'value':[0]}}

        while True:
            arg = self.Q_c2g.get()
            if arg == '_q_u_i_t_':
                self.stp = True  #用于终止主程序
                break

            stimulus_arg, self.marker_event = arg  #marker is a dict

            self.lock.acquire()
            [
                self.stimuli[id].reset(**stimulus_arg[id])
                for id in stimulus_arg
            ]  #更新刺激实例的参数
            self.ask_4_update_gui = True  #请求刷新
            self.lock.release()
        print('[guiengine] sub thread ended')

    def StartRun(self):
        print('[guiengine] process started')
        self.E_g2c.set()
        clock = pygame.time.Clock()
        # END = 0
        while True:
            self.screen.fill(self.screen_color)

            if self.ask_4_update_gui:  #子线程请求刷新
                self.update_in_this_frame = True  #将在这一帧刷新
                self.ask_4_update_gui = False

            #.items()方法将stimuli字典转换为列表,元素为元祖,k[0]对应ID, k[1]为具体的刺激对象实例
            # 意思是按照layer属性排序
            stis = sorted(self.stimuli.items(), key=lambda k: k[1].layer)
            [s[1].show() for s in stis]  #按照图层书序顺序绘图,layer越大,越顶层
            pygame.display.flip()  #该帧刷新完毕

            if not SCREEN_SYNC: clock.tick(self.Fps)

            # 有刷新请求,且在该帧完成了刷新
            if self.update_in_this_frame:
                _clk = global_clock()
                if len(self.marker_event) > 0:  #确实接受到了marker
                    for ky in self.marker_event:  # 将时间戳记录下来
                        self.marker_event[ky]['timestamp'] = _clk
                    self.marker_sender.send_marker(self.marker_event)
                self.update_in_this_frame = False

            pygame.event.get()
            if self.stp: break  #只能通过主控结束

        pygame.quit()
        [self.stimuli[id].release() for id in self.stimuli]  #更新刺激实例的参数

        print('[guiengine] process exit')
Exemple #3
0
class bciApp(bciCore):
    def __init__(self):
        super(bciApp,self).__init__(config_path = r'./config.js')

        self.PHASES = [ {'name':'start','next':'test','duration':1},
                        {'name':'test','next':'relax','duration':7},
                        {'name':'relax','next':'test','duration':5},
                        {'name':'rrelax','next':'stop','duration':1}]

        self.CODER = DefaultCoder()
        
        w = win32api.GetSystemMetrics(win32con.SM_CXSCREEN)
        h = win32api.GetSystemMetrics(win32con.SM_CYSCREEN)
        
        camera_h = 2*240
        camera_w = 2*320

        layout = {'screen': {'size': (w, h), 'color': (0, 0, 0), 'type': 'normal',
                             'Fps': 60, 'caption': 'this is an example'},
                  'camera':{'class':'MjpegStream','parm':{'size':(camera_w,camera_h),'position':(int(w/2),int(h/2)),
                            'anchor':'center','visible':True,'start':True,'url':'http://192.168.1.1:8080/?action=stream'}},
                  'ssvep1': {'class': 'sinCircle', 'parm': {'radius':65, 'position': (int(0.5*w-320-65), int(0.5*h-240+30)),
                        'text':'forward','textsize':20,'frequency': 6.6, 'visible': True, 'start': False}},
                  'ssvep2': {'class': 'sinCircle', 'parm': {'radius':65, 'position': (int(0.5*w-320-65), int(0.5*h)),
                        'text':'left','textsize':20,'frequency': 7.6, 'visible': True, 'start': False}},
                  'ssvep3': {'class': 'sinCircle', 'parm': {'radius':65, 'position': (int(0.5*w-320-65), int(0.5*h+240-30)),
                        'text':'r-left','textsize':20,'frequency': 8.6, 'visible': True, 'start': False}},
                  'ssvep4': {'class': 'sinCircle', 'parm': {'radius':65, 'position': (int(0.5*w+320+65), int(0.5*h-240+30)),
                        'text':'backward','textsize':20,'frequency': 9.3, 'visible': True, 'start': False}},
                  'ssvep5': {'class': 'sinCircle', 'parm': {'radius':65, 'position': (int(0.5*w+320+65), int(0.5*h)),
                        'text':'right','textsize':20,'frequency': 12.2, 'visible': True, 'start': False}},
                  'ssvep6': {'class': 'sinCircle', 'parm': {'radius':65, 'position': (int(0.5*w+320+65), int(0.5*h+240-30)),
                        'text':'r-right','textsize':20,'frequency': 13.8, 'visible': True, 'start': False}},
                  }

        self.gui = GuiIF(None,layout)
        _ = multiprocessing.Process(target=guiengine_proc,args=(self.gui.args,))
        _.start()
        self.gui.wait()

        sp_ip = self.configs['signal_processing']['sp_host_ip']
        sp_port = self.configs['signal_processing']['sp_host_port']
        self.marker = Marker((sp_ip,sp_port))

        self.TEST_NUM = 12
        self.test_count = 1
        
        self.ROBOT = WIFIROBOT_CTR()

    def transition(self,phase):
        write_log(phase)
        if phase == 'test':
            self.gui.update({'ssvep1': {'start': True,'bordercolor':(0,0,0)}, 'ssvep2': {'start': True,'bordercolor':(0,0,0)}, 'ssvep3': {'start': True,'bordercolor':(0,0,0)},
                             'ssvep4': {'start': True,'bordercolor':(0,0,0)},'ssvep5': {'start': True,'bordercolor':(0,0,0)},'ssvep6': {'start': True,'bordercolor':(0,0,0)}}, {})

            t = global_clock()
            self.marker.send_marker({'process':{'value':[1],'timestamp':[t]}})    #开始测试

        elif phase == 'relax':
            self.gui.update({'ssvep1': {'start': False,'bordercolor':(0,0,0)}, 'ssvep2': {'start': False,'bordercolor':(0,0,0)}, 'ssvep3': {'start': False,'bordercolor':(0,0,0)},
                             'ssvep4': {'start': False,'bordercolor':(0,0,0)},'ssvep5': {'start': False,'bordercolor':(0,0,0)},'ssvep6': {'start': False,'bordercolor':(0,0,0)}}, {})

            self.marker.send_marker({'process': {'value': [2],'timestamp':[global_clock()]}})  #测试完成

            self.test_count += 1
            if self.test_count > self.TEST_NUM:
                self.change_phase('rrelax')

    def stop_run(self):
        self.marker.send_marker({'endsigpro': {'value':[1],'timestamp':[global_clock()]}})  #测试完成
        self.gui.quit()
        self.ROBOT.close()

    def process(self,result):
        if result is not None:
            print(result)
            self.gui.update({'ssvep%s'%(result+1): {'bordercolor':(255,0,0)}},{})
            self.ROBOT.go(cmdss[result][0],cmdss[result][1])