Exemplo n.º 1
0
    def onShowHideParamPanel(self, event):
        if DEBUGGING: print('SetupStimuliDialog.onShowHideParamPanel()')

        pos = list(self.setting_p.GetPosition())
        if self.showHideAnimation == "":  # not during animation
            lbl = self.showHideBtn.GetLabel()
            if pos[0] < 0: self.showHideAnimation = "show"
            else: self.showHideAnimation = "hide"
        w = self.setting_p_sz[0]
        btn_w = self.showHideBtn.GetSize()[0]
        mDist = (w - btn_w) / self.ani_fr
        if self.showHideAnimation == "show":
            pos[0] += mDist
            self.setting_p.SetPosition(tuple(pos))
            if pos[0] >= 5:
                self.showHideAnimation = ""
                set_img_for_btn(
                    path.join(self.e_gui_path, "input/img_arrow_left.png"),
                    self.showHideBtn)
            else:
                wx.CallLater(self.ani_intv, self.onShowHideParamPanel, None)
        elif self.showHideAnimation == "hide":
            pos[0] -= mDist
            self.setting_p.SetPosition(tuple(pos))
            if pos[0] <= -w + btn_w + mDist:
                self.showHideAnimation = ""
                set_img_for_btn(
                    path.join(self.e_gui_path, "input/img_arrow_right.png"),
                    self.showHideBtn)
            else:
                wx.CallLater(self.ani_intv, self.onShowHideParamPanel, None)
Exemplo n.º 2
0
 def onShowScript(self, event):
     if DEBUGGING: print('EGUIFrame.onShowScript()')
     event.Skip()
     self.flag_script_visible = not self.flag_script_visible
     btn = event.GetEventObject()
     if self.flag_script_visible == True:
         self.sPanel.stc.Show()  # hide script
         for w in self.sPanel.widgets[0]:
             w.Show()  # hide script related widgets
         set_img_for_btn(
             path.join(self.e_gui_path, "input/img_script_hide.png"), btn)
     else:
         self.sPanel.stc.Hide()  # show script
         for w in self.sPanel.widgets[0]:
             w.Hide()  # show script related widgets
         set_img_for_btn(
             path.join(self.e_gui_path, "input/img_script_show.png"), btn)
     ### show/hide marker buttons in main panel
     for item in self.mPanel.items.keys():
         if item in self.iPanel.choice_items:
             valWid = wx.FindWindowByName(item + "_cho", self.mPanel)
         else:
             valWid = wx.FindWindowByName(item + "_txt", self.mPanel)
         if valWid == None or valWid.IsShown() == False: continue
         btn = wx.FindWindowByName(item + "_marker_btn", self.mPanel)
         if self.flag_script_visible == True: btn.Show()
         else: btn.Hide()
     self.mPanel.gbs.Layout()
     self.sPanel.gbs.Layout()
Exemplo n.º 3
0
    def onShowHide(self, event):
        ''' show/hide basic items
        '''
        if DEBUGGING: print('MainPanel.onShowHide()')
        event.Skip()

        def _func(item):
            # show/hide item title and its help button
            _w = []
            _w.append(wx.FindWindowByName("%s_sTxt" % (item), self))
            if item == 'setup_stimuli':
                _w.append(wx.FindWindowByName("%s_btn" % (item), self))
            if item in self.parent.iPanel.choice_items:
                _w.append(wx.FindWindowByName("%s_cho" % (item), self))
            else:
                _w.append(wx.FindWindowByName("%s_txt" % (item), self))
            if self.parent.flag_script_visible == True:
                _w.append(wx.FindWindowByName("%s_marker_btn" % (item), self))
            if self.flag_bItemsList1_shown == False:
                for widget in _w:
                    widget.Show()
                    self.items[item] = self.getItemVal(item)[
                        1]  # store item and its value
            elif self.flag_bItemsList1_shown == True:
                for widget in _w:
                    widget.Hide()
                    __ = self.items.pop(
                        item, None
                    )  # remove the item from the current item dictionary

        for item in self.parent.iPanel.bItemsList[
                1]:  # items hidden by default among basic items (item_info[0])
            _func(item)
        for item in sorted(self.parent.iPanel.item_info[2].keys(
        )):  # items automatically added when stimuli path is selected
            _func(item)

        ### change arrow button image and flag value
        if self.flag_bItemsList1_shown == False:
            self.flag_bItemsList1_shown = True
            set_img_for_btn(
                path.join(self.parent.e_gui_path, "input/img_arrow_up.png"),
                self.sh_btn)
        elif self.flag_bItemsList1_shown == True:
            self.flag_bItemsList1_shown = False
            set_img_for_btn(
                path.join(self.parent.e_gui_path, "input/img_arrow_down.png"),
                self.sh_btn)

        self.gbs.Layout()
        #self.Layout()
        self.SetupScrolling()
Exemplo n.º 4
0
    def onShowHide(self, event):
        ''' show/hide basic items
        '''
        if DEBUGGING: print('ItemPanel.onShowHide()')
        event.Skip()

        def _func(item):
            # show/hide item title and its help button
            sTxt = wx.FindWindowByName("%s_sTxt" % (item), self)
            helpBtn = wx.FindWindowByName("%s_help_btn" % (item), self)
            if self.flag_bItemsList1_shown == False:
                sTxt.Show()
                helpBtn.Show()
            elif self.flag_bItemsList1_shown == True:
                sTxt.Hide()
                helpBtn.Hide()

        for item in self.bItemsList[
                1]:  # items hidden by default among basic items (item_info[0])
            _func(item)
        for item in sorted(self.item_info[2].keys(
        )):  # items automatically added when stimuli path is selected
            _func(item)

        ### change arrow button image and flag value
        if self.flag_bItemsList1_shown == False:
            self.flag_bItemsList1_shown = True
            set_img_for_btn(
                path.join(self.parent.e_gui_path, "input/img_arrow_up.png"),
                self.sh_btn)
        elif self.flag_bItemsList1_shown == True:
            self.flag_bItemsList1_shown = False
            set_img_for_btn(
                path.join(self.parent.e_gui_path, "input/img_arrow_down.png"),
                self.sh_btn)

        self.gbs.Layout()
        self.Layout()
        self.SetupScrolling()
Exemplo n.º 5
0
    def onShowHideOptionalItems(self, event):
        ''' show/hide optional items
        '''
        if DEBUGGING: print('ItemPanel.onShowHideOptionalItems()')
        event.Skip()
        for item in sorted(self.item_info[1].keys()):
            # show/hide item title and its help,add button
            sTxt = wx.FindWindowByName("%s_sTxt" % (item), self)
            helpBtn = wx.FindWindowByName("%s_help_btn" % (item), self)
            addBtn = wx.FindWindowByName("%s_add_btn" % (item), self)
            if self.flag_optionItems_shown == False:
                sTxt.Show()
                helpBtn.Show()
                addBtn.Show()
            elif self.flag_optionItems_shown == True:
                sTxt.Hide()
                helpBtn.Hide()
                addBtn.Hide()

        ### change arrow button image, label and flag value
        if self.flag_optionItems_shown == False:
            self.flag_optionItems_shown = True
            set_img_for_btn(
                path.join(self.parent.e_gui_path, "input/img_arrow_up.png"),
                self.sh_op_btn, False)
            self.sh_op_btn.SetLabel('Hide optional items')
        elif self.flag_optionItems_shown == True:
            self.flag_optionItems_shown = False
            set_img_for_btn(
                path.join(self.parent.e_gui_path, "input/img_arrow_down.png"),
                self.sh_op_btn, False)
            self.sh_op_btn.SetLabel('Show optional items')

        self.gbs.Layout()
        self.Layout()
        self.SetupScrolling()
Exemplo n.º 6
0
    def onSelectCorrectStim(self, event):
        if DEBUGGING: print('SetupStimuliDialog.onSelectCorrectStim()')

        objName = event.GetEventObject().GetName()
        clicked_idx = int(
            objName.split("_")[-1])  # index of clicked response stimulus
        for cbi in range(len(self.rsCorrectBtns)):
            cBtn = self.rsCorrectBtns[cbi]
            if cbi == clicked_idx:
                if self.rsCorrIdx != cbi:
                    set_img_for_btn(
                        path.join(self.e_gui_path, "input/img_apply_c.png"),
                        cBtn)
                    self.rsCorrIdx = clicked_idx
                else:
                    set_img_for_btn(
                        path.join(self.e_gui_path, "input/img_apply.png"),
                        cBtn)
                    self.rsCorrIdx = -1
            else:
                set_img_for_btn(
                    path.join(self.e_gui_path, "input/img_apply.png"), cBtn)
Exemplo n.º 7
0
    def __init__(self):
        if DEBUGGING: print('EGUIFrame.__init__()')

        ### set up application folder
        if getattr(sys, 'frozen', False):
            ### If the application is run as a bundle, the pyInstaller bootloader
            # extends the sys module by a flag frozen=True and sets the app
            # path into variable _MEIPASS'.
            self.e_gui_path = sys._MEIPASS

            ### TO BE FIXED
            # After bundling with pyInstaller, running App failed, which seems to be the path issue.
            # The above sys._MEIPASS didn't work as expected.
            # When the path was stripped three times
            # (because e_gui.app/Contents/MacOS is where the e_gui executable is located)
            # using path.dirname, the e_gui.app successfully launched
            # Maybe this issue of pyInstaller might get fixed later
            for i in range(3):
                self.e_gui_path = path.dirname(self.e_gui_path)
        else:
            self.e_gui_path = path.dirname(path.abspath(__file__))

        self.flag_img = False
        self.flag_snd = False
        self.flag_mov = False
        self.flag_script_visible = False
        self.allowed_img_ext = ['png', 'jpg', 'tif', 'tiff']
        self.allowed_snd_ext = ['wav']
        self.allowed_mov_ext = ['mov', 'mp4', 'avi']

        w_pos = (0, 25)
        w_size = (wx.Display(0).GetGeometry()[2],
                  wx.Display(0).GetGeometry()[3] - w_pos[1])
        self.w_sz = w_size  # initial size

        wx.Frame.__init__(self,
                          None,
                          -1,
                          "Experimenter_GUI - %s" % __version__,
                          pos=w_pos,
                          size=w_size)
        #style=wx.DEFAULT_FRAME_STYLE^(wx.RESIZE_BORDER|wx.MAXIMIZE_BOX))
        self.SetBackgroundColour('#333333')
        #self.ShowFullScreen(True)
        #self.Bind(wx.EVT_SIZE, self.onSizing)

        ### set window size exactly to self.w_sz without menubar/border/etc.
        _diff = (self.GetSize()[0] - self.GetClientSize()[0],
                 self.GetSize()[1] - self.GetClientSize()[1])
        _sz = (w_size[0] + _diff[0], w_size[1] + _diff[1])
        self.SetSize(_sz)

        ### font setup
        if 'darwin' in sys.platform: _font = "Monaco"
        else: _font = "Courier"
        fontSz = 8
        self.base_script_font = wx.Font(20, wx.FONTFAMILY_DEFAULT, wx.NORMAL,
                                        wx.FONTWEIGHT_NORMAL, False, "Courier",
                                        wx.FONTENCODING_SYSTEM)
        self.fonts = []  # 0:smll, 1:default, larger fonts as index gets larger
        for i in range(5):
            self.fonts.append(
                wx.Font(fontSz,
                        wx.FONTFAMILY_SWISS,
                        wx.FONTSTYLE_NORMAL,
                        wx.FONTWEIGHT_BOLD,
                        False,
                        faceName=_font))
            fontSz += 2
        dc = wx.WindowDC(self)
        dc.SetFont(self.fonts[1])

        ### set up panels
        ip_sz = (270, w_size[1] - 40)
        ip_pos = (0, 40)
        sp_sz = (670, w_size[1] - 60)
        sp_pos = (w_size[0] - sp_sz[0], 40)
        mp_sz = (w_size[0] - ip_sz[0] - sp_sz[0], w_size[1] - 80)
        mp_pos = (ip_sz[0], 80)
        self.ip_sz = ip_sz
        self.mp_sz = mp_sz
        self.sp_sz = sp_sz
        title = wx.StaticText(self, -1, "Item list", pos=(ip_pos[0], 3))
        title.SetFont(self.fonts[4])
        title.SetForegroundColour('#DDDDDD')
        self.iPanel = ItemPanel(self, pos=ip_pos, size=ip_sz)
        title = wx.StaticText(self,
                              -1,
                              "Set up items in script",
                              pos=(mp_pos[0], 3))
        title.SetFont(self.fonts[4])
        title.SetForegroundColour('#DDDDDD')
        sTxt = wx.StaticText(self,
                             -1,
                             " - Change a choice box item with mouse, or",
                             pos=(mp_pos[0], title.GetPosition()[1] +
                                  title.GetSize()[1] + 2))
        sTxt.SetFont(self.fonts[2])
        sTxt.SetForegroundColour('#DDDDDD')
        sTxt = wx.StaticText(
            self,
            -1,
            " type a text in a text-box and press Return-key.",
            pos=(mp_pos[0], sTxt.GetPosition()[1] + sTxt.GetSize()[1] + 2))
        sTxt.SetFont(self.fonts[2])
        sTxt.SetForegroundColour('#DDDDDD')
        self.mPanel = MainPanel(self, pos=mp_pos, size=mp_sz)
        title = wx.StaticText(self, -1, "Result script", pos=(sp_pos[0], 3))
        title.SetFont(self.fonts[4])
        title.SetForegroundColour('#DDDDDD')
        btn = wx.Button(self,
                        -1,
                        "",
                        name="show_script_btn",
                        pos=(sp_pos[0] + title.GetSize()[0] + 5, 0),
                        size=(25, 20))
        set_img_for_btn(
            path.join(self.e_gui_path, "input/img_script_show.png"), btn)
        btn.Bind(wx.EVT_LEFT_UP, self.onShowScript)
        self.sPanel = ScriptPanel(self, pos=sp_pos, size=sp_sz)

        ### Connecting key-inputs with some functions
        exit_BtnID = wx.NewIdRef(count=1)
        #esc_BtnID = wx.NewIdRef(count=1)
        self.Bind(wx.EVT_MENU, self.quit, id=exit_BtnID)
        #self.Bind(wx.EVT_MENU, self.onESC, id = esc_BtnID)
        accel_tbl = wx.AcceleratorTable([(wx.ACCEL_CMD, ord('Q'), exit_BtnID)])
        #(wx.ACCEL_NORMAL, wx.WXK_ESCAPE, esc_BtnID) ])
        self.SetAcceleratorTable(accel_tbl)

        #msg = "Click OK button (or press ENTER key) to start the app.\nDialog for asking a series of questions to determine stimuli paths/correct stimulus/etc will appear.\n\nIf stimuli for trials should be specifically ordered, stimuli filenames should follow specific rules.\nIf you are not sure about it, cancel the dialog box and check the rules by pressing info(i) button next to 'setup_stimuli' in the left panel."
        #show_msg(msg, size=(400, 280))
        wx.CallLater(1, self.mPanel.setUpStimuli, None)
Exemplo n.º 8
0
    def onClickApply(self, event):
        ''' clicked apply button 
        (for number_of_trials, number_of_experimental_stimuli or number_of_response_stimuli)
        '''
        if DEBUGGING: print('SetupStimuliDialog.onClickApply()')

        for key in self.main_param:
            valObj = wx.FindWindowByName(key, self)
            val = valObj.GetValue()
            val_int = None
            try:
                val_int = int(val)
            except:
                pass
            if val_int == None:
                valObj.SetValue("0")
                show_msg("%s has invalid number" % (key))
                return
            self.return_val[key] = val_int

        #objName = event.GetEventObject().GetName()
        #if objName.startswith("apply_"): key = objName.replace("apply_", "")
        #else: key = objName

        if key == "number_of_trials":
            # if number_of_trials chnages, init other numbers
            self.return_val["number_of_experimental_stimuli"] = 0
            valObj = wx.FindWindowByName("number_of_experimental_stimuli",
                                         self)
            valObj.SetValue("0")
            self.return_val["number_of_response_stimuli"] = 0
            valObj = wx.FindWindowByName("number_of_response_stimuli", self)
            valObj.SetValue("0")

        self.return_val["types_of_es"] = []
        self.return_val["types_of_rs"] = []
        self.return_val["rects_of_es"] = []
        self.return_val["rects_of_rs"] = []
        self.return_val["paths_of_es"] = []
        self.return_val["paths_of_rs"] = []
        self.sliders = []

        ### set up rects
        for txt in self.esRectTxts:
            txt.Destroy()
        self.esRectTxts = []
        for btn in self.esOpenBtns:
            btn.Destroy()
        self.esOpenBtns = []
        for txt in self.rsRectTxts:
            txt.Destroy()
        self.rsRectTxts = []
        for btn in self.rsOpenBtns:
            btn.Destroy()
        self.rsOpenBtns = []
        for btn in self.rsCorrectBtns:
            btn.Destroy()
        self.rsCorrectBtns = []
        nes = self.return_val["number_of_experimental_stimuli"]
        nrs = self.return_val["number_of_response_stimuli"]
        num_of_stim = nes + nrs
        if num_of_stim == 1: rects = [[0.5, 0.5, -1, -1]]
        elif num_of_stim == 2:
            if nes == 1 and nrs == 1:
                rects = [[0.5, 0.5, -1, -1], [0.5, 0.8, -1, -1]]
            else:
                rects = [[0.25, 0.5, -1, -1], [0.75, 0.5, -1, -1]]
        elif num_of_stim == 3:
            rects = [[0.5, 0.5, -1, -1], [0.25, 0.8, -1, -1],
                     [0.75, 0.8, -1, -1]]
        else:
            columns = sqrt(num_of_stim)
            rows = int(columns)
            if columns % 1 > 0: columns += 1
            columns = int(columns)
            rects = []
            for r in range(rows):
                if r == rows - 1:  # last row
                    w = 1.0 / (num_of_stim - columns * (rows - 1))
                else:
                    w = 1.0 / columns  # width for each stimulus
                h = 1.0 / rows  # height for each stimulus
                for c in range(columns):
                    rects.append([w * c + w / 2, h * r + h / 2, -1, -1])
        self.return_val["rects_of_es"] = rects[:nes]
        self.return_val["rects_of_rs"] = rects[nes:]
        for si in range(num_of_stim):
            if si < nes: tName = "es_rect_%i" % (si)
            else: tName = "rs_rect_%i" % (si - nes)
            r = rects[si]
            txt = wx.TextCtrl(self,
                              -1,
                              value="[%.3f, %.3f, -1, -1]" % (r[0], r[1]),
                              name=tName,
                              size=(170, -1),
                              style=wx.TE_PROCESS_ENTER)
            txt.Bind(wx.EVT_TEXT_ENTER, self.onRectTextChange)
            pos = (int(self.w_sz[0] * r[0]) - txt.GetSize()[0] / 2,
                   int(self.w_sz[1] * r[1]) + self.ds_sz[1] / 2 + 5)
            txt.SetPosition(pos)
            bName = tName.replace("_rect_", "_open_btn_")
            oBtn = wx.Button(self, -1, label='', name=bName, size=(20, 20))
            oBtn.Bind(wx.EVT_LEFT_DOWN, self.onSelectStim)
            set_img_for_btn(
                path.join(self.e_gui_path, "input/img_open_folder.png"), oBtn)
            pos = (int(self.w_sz[0] * r[0]) - oBtn.GetSize()[0] / 2,
                   int(self.w_sz[1] * r[1]) - oBtn.GetSize()[1] / 2 -
                   self.ds_sz[1] / 2)
            oBtn.SetPosition(pos)
            lName = tName.replace("_rect_", "_stim_list_")
            if si >= nes:  # this is response stimulus
                bName = tName.replace("_rect_", "_correct_btn_")
                cBtn = wx.Button(self, -1, label='', name=bName, size=(20, 20))
                cBtn.Bind(wx.EVT_LEFT_DOWN, self.onSelectCorrectStim)
                set_img_for_btn(
                    path.join(self.e_gui_path, "input/img_apply.png"), cBtn)
                pos = (int(self.w_sz[0] * r[0]) + self.ds_sz[0] / 2 -
                       cBtn.GetSize()[0], int(self.w_sz[1] * r[1]) -
                       cBtn.GetSize()[1] / 2 - self.ds_sz[1] / 2)
                cBtn.SetPosition(pos)
            if si < nes:  # this is experimental stimulus
                self.esRectTxts.append(txt)
                self.esOpenBtns.append(oBtn)
                self.return_val["types_of_es"].append(None)
                self.return_val["paths_of_es"].append([])
            else:  # response stimulus
                self.rsRectTxts.append(txt)
                self.rsOpenBtns.append(oBtn)
                self.rsCorrectBtns.append(cBtn)
                self.sliders.append(None)
                self.return_val["types_of_rs"].append(None)
                self.return_val["paths_of_rs"].append([])

        self.Refresh()
        self.setting_p.Raise()
Exemplo n.º 9
0
    def __init__(self, parent):
        if DEBUGGING: print('SetupStimuliDialog.__init__()')

        self.parent = parent
        self.e_gui_path = parent.parent.e_gui_path

        self.main_param = [
            'number_of_trials', 'number_of_experimental_stimuli',
            'number_of_response_stimuli'
        ]
        self.return_val = dict(number_of_trials=0,
                               number_of_experimental_stimuli=0,
                               number_of_response_stimuli=0,
                               types_of_es=[],
                               types_of_rs=[],
                               rects_of_es=[],
                               rects_of_rs=[],
                               paths_of_es=[],
                               paths_of_rs=[],
                               movie_module=None)
        self.setting_p_sz = (350, 400)
        self.ds_sz = (100, 100)  # default size of a stimulus rectangle
        self.esRectTxts = []  # textctrls for experimental stimuli rects
        self.rsRectTxts = []  # textctrls for response stimuli rects
        self.esOpenBtns = [
        ]  # buttons for opening folder for experimental stimuli
        self.rsOpenBtns = []  # buttons for opening folder for response stimuli
        self.rsCorrectBtns = [
        ]  # buttons for selecting correct response stimulus
        self.rsCorrIdx = -1  # index of response stimuli, indicating correct response
        self.sliders = []  # user response slider
        ### for show/hide-setting animation
        self.showHideAnimation = ""
        self.ani_fr = 15  # frames for animation
        self.ani_intv = 200 / self.ani_fr  # interval between frames (in milliseconds)

        w_pos = (0, 25)
        w_size = (wx.Display(0).GetGeometry()[2],
                  wx.Display(0).GetGeometry()[3] - w_pos[1])
        self.w_sz = w_size
        wx.Dialog.__init__(self,
                           parent,
                           -1,
                           "Stimuli setup",
                           pos=w_pos,
                           size=w_size)
        self.SetBackgroundColour('#AAAABB')

        self.setting_p = wx.Panel(self, -1, pos=(5, 5), size=self.setting_p_sz)
        self.setting_p.SetBackgroundColour('#999999')
        self.gbs = wx.GridBagSizer(0, 0)
        bw = 5
        row = 0
        col = 0
        sTxt = wx.StaticText(self.setting_p, -1, "")
        self.gbs.Add(sTxt, pos=(row, col), span=(1, 2), flag=wx.ALL, border=bw)
        col += 2
        self.showHideBtn = wx.Button(self.setting_p, -1, "", size=(30, 30))
        set_img_for_btn(path.join(self.e_gui_path, "input/img_arrow_left.png"),
                        self.showHideBtn)
        self.showHideBtn.Bind(wx.EVT_LEFT_DOWN, self.onShowHideParamPanel)
        self.gbs.Add(self.showHideBtn, pos=(row, col), flag=wx.ALL, border=bw)

        row += 1
        col = 0
        sTxt = wx.StaticText(self.setting_p, -1,
                             "Please specify below three parameters first.")
        self.gbs.Add(sTxt, pos=(row, col), span=(1, 3), flag=wx.ALL, border=bw)

        row += 1
        col = 0
        sTxt = wx.StaticText(self.setting_p, -1, "")
        self.gbs.Add(sTxt, pos=(row, col), span=(1, 3), flag=wx.ALL, border=bw)

        row += 1
        col = 0
        sTxt = wx.StaticText(self.setting_p, -1, "Number of trials")
        self.gbs.Add(sTxt, pos=(row, col), flag=wx.ALL, border=bw)
        col += 1
        txt = wx.TextCtrl(self.setting_p,
                          -1,
                          value="0",
                          name="number_of_trials",
                          size=(35, -1),
                          style=wx.TE_PROCESS_ENTER)
        txt.Bind(wx.EVT_TEXT_ENTER, self.onClickApply)
        self.gbs.Add(txt, pos=(row, col), flag=wx.ALL, border=bw)
        col += 1
        sTxt = wx.StaticText(self.setting_p, -1, "")
        self.gbs.Add(sTxt, pos=(row, col), flag=wx.ALL, border=bw)

        row += 1
        col = 0
        sTxt = wx.StaticText(self.setting_p, -1, "")
        self.gbs.Add(sTxt, pos=(row, col), span=(1, 3), flag=wx.ALL, border=bw)

        row += 1
        col = 0
        sTxt = wx.StaticText(self.setting_p, -1,
                             "Number of experimental stimuli per trial")
        self.gbs.Add(sTxt,
                     pos=(row, col),
                     flag=wx.ALL | wx.ALIGN_BOTTOM,
                     border=bw)
        col += 1
        txt = wx.TextCtrl(self.setting_p,
                          -1,
                          value="0",
                          name="number_of_experimental_stimuli",
                          size=(35, -1),
                          style=wx.TE_PROCESS_ENTER)
        txt.Bind(wx.EVT_TEXT_ENTER, self.onClickApply)
        self.gbs.Add(txt, pos=(row, col), flag=wx.ALL, border=bw)
        col += 1
        sTxt = wx.StaticText(self.setting_p, -1, "")
        self.gbs.Add(sTxt, pos=(row, col), flag=wx.ALL, border=bw)

        row += 1
        col = 0
        sTxt = wx.StaticText(self.setting_p, -1,
                             "Number of response stimuli per trial")
        self.gbs.Add(sTxt,
                     pos=(row, col),
                     flag=wx.ALL | wx.ALIGN_BOTTOM,
                     border=bw)
        col += 1
        txt = wx.TextCtrl(self.setting_p,
                          -1,
                          value="0",
                          name="number_of_response_stimuli",
                          size=(35, -1),
                          style=wx.TE_PROCESS_ENTER)
        txt.Bind(wx.EVT_TEXT_ENTER, self.onClickApply)
        self.gbs.Add(txt, pos=(row, col), flag=wx.ALL, border=bw)
        col += 1
        sTxt = wx.StaticText(self.setting_p, -1, "")
        self.gbs.Add(sTxt, pos=(row, col), flag=wx.ALL, border=bw)

        row += 1
        col = 0
        btn = wx.Button(self.setting_p,
                        -1,
                        "Apply",
                        size=(self.setting_p_sz[0] - 40, -1))
        btn.Bind(wx.EVT_LEFT_DOWN, self.onClickApply)
        self.gbs.Add(btn,
                     pos=(row, col),
                     span=(1, 2),
                     flag=wx.ALL | wx.ALIGN_RIGHT | wx.ALIGN_TOP,
                     border=0)
        col += 2
        sTxt = wx.StaticText(self.setting_p, -1, "")
        self.gbs.Add(sTxt, pos=(row, col), flag=wx.ALL, border=bw)

        row += 1
        col = 0
        sTxt = wx.StaticText(self.setting_p, -1, "")
        self.gbs.Add(sTxt, pos=(row, col), span=(1, 3), flag=wx.ALL, border=bw)

        row += 1
        col = 0
        sTxt = wx.StaticText(
            self.setting_p, -1,
            " * Response stimulus is a clickable text or image to accept user-response. If there will be no dedicated response text or image and experimental stimuli will be also used for user-response, just consider them as response stimuli in this setup window."
        )
        sTxt.Wrap(self.setting_p_sz[0] - 50)
        self.gbs.Add(sTxt,
                     pos=(row, col),
                     span=(1, 2),
                     flag=wx.ALL | wx.ALIGN_TOP,
                     border=0)
        col += 2
        sTxt = wx.StaticText(self.setting_p, -1, "")
        self.gbs.Add(sTxt, pos=(row, col), flag=wx.ALL, border=bw)

        self.setting_p.SetSizer(self.gbs)
        self.gbs.Layout()

        okButton = wx.Button(self, wx.ID_OK, "Finish setup")
        okButton.SetPosition(
            (self.w_sz[0] - okButton.GetSize()[0] * 2 - 20, self.w_sz[1] - 75))
        okButton.Bind(wx.EVT_LEFT_DOWN, self.onCheck)
        cancelButton = wx.Button(self, wx.ID_CANCEL, "Cancel")
        cancelButton.SetPosition(
            (okButton.GetPosition()[0] + okButton.GetSize()[0] + 5,
             self.w_sz[1] - 75))

        self.Bind(wx.EVT_PAINT, self.onPaint)
Exemplo n.º 10
0
    def __init__(self, parent, pos, size):
        self.parent = parent
        if DEBUGGING: print('ScriptPanel.__init__()')
        wx.Panel.__init__(self, parent, -1, pos=pos, size=size)
        self.SetBackgroundColour('#333333')
        
        self.fSzSTC = 12
        self.cmi = -1 # current marker index
        self.markerIds = []
        btnSz = (30,-1)
        self.widgets = [[], []] # widgets others than STC, the first widget list belongs to STC (meaning when Script is hidden, these widgets will be hidden as well; marker button, zoom button), the second widget list contaings others such as save, load button.
        self.scriptChangedByMainPanel = '' # for storing script when it was changed by manipulating widgets in mainPanel (to compare this with script when it's saved to check whether manual script change occurred)

        self.gbs = wx.GridBagSizer(0,0)
        bw = 2 
       
        row=0; col=0
        stc_sz = (size[0]-4, size[1]-100)
        self.stc = STC(self, (2,0), stc_sz)
        self.gbs.Add(self.stc, pos=(row,col), span=(1,10), flag=wx.EXPAND|wx.ALL, border=bw)
        
        col += 10
        self.gbs.Add(wx.StaticText(self, -1, "", size=(1,1)), pos=(row,col), flag=wx.EXPAND|wx.ALL, border=bw)
       
        row += 1
        col = 0
        sTxt = wx.StaticText(self, -1, "Marker")
        self.widgets[0].append(sTxt)
        sTxt.SetForegroundColour('#CCCCCC')
        self.gbs.Add(sTxt, pos=(row,col), flag=wx.ALIGN_CENTER_VERTICAL|wx.ALL, border=bw)

        col += 1
        btn = wx.Button(self, -1, label="marker", name="prevM", size=btnSz)
        set_img_for_btn(path.join(self.parent.e_gui_path, "input/img_marker_prev.png"), btn)
        self.widgets[0].append(btn)
        btn.Bind(wx.EVT_LEFT_UP, self.onNavMarkers)
        self.gbs.Add(btn, pos=(row,col), flag=wx.ALIGN_CENTER_VERTICAL|wx.ALL, border=bw)
       
        col += 1
        btn = wx.Button(self, -1, label="marker", name="nextM", size=btnSz)
        set_img_for_btn(path.join(self.parent.e_gui_path, "input/img_marker_next.png"), btn)
        self.widgets[0].append(btn)
        btn.Bind(wx.EVT_LEFT_UP, self.onNavMarkers)
        self.gbs.Add(btn, pos=(row,col), flag=wx.ALIGN_CENTER_VERTICAL|wx.ALL, border=bw)

        col += 1
        sTxt = wx.StaticText(self, -1, "Zoom")
        self.widgets[0].append(sTxt)
        sTxt.SetForegroundColour('#CCCCCC')
        self.gbs.Add(sTxt, pos=(row,col), flag=wx.ALIGN_CENTER_VERTICAL|wx.ALL, border=bw)

        col += 1
        btn = wx.Button(self, -1, label="", name="zoom+", size=btnSz)
        set_img_for_btn(path.join(self.parent.e_gui_path, "input/img_zoomin.png"), btn)
        self.widgets[0].append(btn)
        btn.Bind(wx.EVT_LEFT_UP, self.onZoom)
        self.gbs.Add(btn, pos=(row,col), flag=wx.ALIGN_CENTER_VERTICAL|wx.ALL, border=bw)

        col += 1
        btn = wx.Button(self, -1, label="", name="zoom-", size=btnSz)
        set_img_for_btn(path.join(self.parent.e_gui_path, "input/img_zoomout.png"), btn)
        self.widgets[0].append(btn)
        btn.Bind(wx.EVT_LEFT_UP, self.onZoom)
        self.gbs.Add(btn, pos=(row,col), flag=wx.ALIGN_CENTER_VERTICAL|wx.ALL, border=bw)

        col += 1 
        self.gbs.Add(wx.StaticText(self, -1, "", size=(1,1)), pos=(row,col), flag=wx.EXPAND|wx.ALL, border=bw)
        
        col += 1
        cho = wx.Choice(self, -1, choices = ["Show: Stimuli_set-up", "Show: Scheduling_stimuli_presentation", "Show: Presenting_text", "Show: Presenting_image", "Show: Presenting_sound", "Show: Presenting_movie", "Show: Writing_result", "Show: Presenting_feedback"])
        self.widgets[0].append(cho)
        cho.Bind(wx.EVT_LEFT_UP, self.onChoiceMarkerTag)
        self.gbs.Add(cho, pos=(row,col), span=(1,4), flag=wx.ALIGN_CENTER_VERTICAL|wx.ALL, border=bw)
        
        col += 4 
        self.gbs.Add(wx.StaticText(self, -1, "", size=(1,1)), pos=(row,col), span=(1,1), flag=wx.EXPAND|wx.ALL, border=bw)
       
        row += 1; col = 0 
        txt = wx.TextCtrl(self, -1, value='SearchText', name="searchTxt", size=(120,-1), style=wx.TE_PROCESS_ENTER)
        self.widgets[0].append(txt)
        txt.Bind(wx.EVT_TEXT_ENTER, self.onSearch)
        self.gbs.Add(txt, span=(1,3), pos=(row,col), flag=wx.ALIGN_CENTER_VERTICAL|wx.ALL, border=bw)
        col += 3 
        btn = wx.Button(self, -1, label="", name="searchBtn", size=btnSz)
        set_img_for_btn(path.join(self.parent.e_gui_path, "input/img_search.png"), btn)
        self.widgets[0].append(btn)
        btn.Bind(wx.EVT_LEFT_UP, self.onSearch)
        self.gbs.Add(btn, pos=(row,col), flag=wx.ALIGN_CENTER_VERTICAL|wx.ALL, border=bw)
        col += 1
        txt = wx.TextCtrl(self, -1, value='ReplaceText', name="replaceTxt", size=(150,-1), style=wx.TE_PROCESS_ENTER)
        self.widgets[0].append(txt)
        self.gbs.Add(txt, span=(1,3), pos=(row,col), flag=wx.ALIGN_CENTER_VERTICAL|wx.ALL, border=bw)
        col += 3
        btn = wx.Button(self, -1, label="Replace-1", name="replaceOneBtn", size=(btnSz[0]*3,btnSz[1]))
        self.widgets[0].append(btn)
        btn.Bind(wx.EVT_LEFT_UP, self.onReplace)
        self.gbs.Add(btn, pos=(row,col), flag=wx.ALIGN_CENTER_VERTICAL|wx.ALL, border=bw)
        col += 1
        btn = wx.Button(self, -1, label="Replace-All", name="replaceAllBtn", size=(btnSz[0]*3,btnSz[1]))
        self.widgets[0].append(btn)
        btn.Bind(wx.EVT_LEFT_UP, self.onReplace)
        self.gbs.Add(btn, pos=(row,col), flag=wx.ALIGN_CENTER_VERTICAL|wx.ALL, border=bw)
        col += 1
        self.gbs.Add(wx.StaticText(self, -1, "", size=(1,1)), span=(1,2), pos=(row,col), flag=wx.EXPAND|wx.ALL, border=bw)

        row += 1
        col = 0
        sTxt = wx.StaticText(self, -1, "FileName (without path)")
        self.widgets[1].append(sTxt)
        sTxt.SetForegroundColour('#CCCCCC')
        self.gbs.Add(sTxt, pos=(row,col), span=(1,4), flag=wx.ALIGN_CENTER_VERTICAL|wx.ALIGN_RIGHT|wx.ALL, border=bw)

        col += 4 
        txt = wx.TextCtrl(self, -1, value='test.py', name="fn", size=(150,-1), style=wx.TE_PROCESS_ENTER)
        self.widgets[1].append(txt)
        txt.Bind(wx.EVT_TEXT_ENTER, self.onSave)
        self.gbs.Add(txt, pos=(row,col), span=(1,3), flag=wx.ALIGN_CENTER_VERTICAL|wx.ALL, border=bw)

        col += 3 
        btn = wx.Button(self, -1, label="Save", name="save", size=(btnSz[0]*3,btnSz[1]), style=wx.ID_SAVE)
        set_img_for_btn(path.join(self.parent.e_gui_path, "input/img_save.png"), btn, False)
        self.widgets[1].append(btn)
        btn.Bind(wx.EVT_LEFT_UP, self.onSave)
        self.gbs.Add(btn, pos=(row,col), flag=wx.ALIGN_CENTER_VERTICAL|wx.ALL, border=bw)
       
        col += 1
        btn = wx.Button(self, -1, label="Load", name="load", size=(btnSz[0]*3,btnSz[1]))
        set_img_for_btn(path.join(self.parent.e_gui_path, "input/img_load.png"), btn, False)
        self.widgets[1].append(btn)
        btn.Bind(wx.EVT_LEFT_UP, self.onLoad)
        self.gbs.Add(btn, pos=(row,col), flag=wx.ALIGN_CENTER_VERTICAL|wx.ALL, border=bw)

        col += 1 
        btn = wx.Button(self, -1, label="RUN", name="run", size=(btnSz[0]*3,btnSz[1]))
        set_img_for_btn(path.join(self.parent.e_gui_path, "input/img_run.png"), btn, False)
        self.widgets[1].append(btn)
        btn.Bind(wx.EVT_LEFT_UP, self.onRun)
        self.gbs.Add(btn, pos=(row,col), flag=wx.ALIGN_CENTER_VERTICAL|wx.ALL, border=bw)
        
        col += 1 
        self.gbs.Add(wx.StaticText(self, -1, "", size=(1,1)), pos=(row,col), flag=wx.EXPAND|wx.ALL, border=bw)

        ### load the base code
        f = open( path.join(self.parent.e_gui_path, 'scripts/base.py'), 'r' )
        txt = f.read()
        f.close()
        for item in self.parent.mPanel.items.keys():
            _, _, txt = self.replaceValTxt(item, txt)
        self.stc.AddText(txt)
        
        ### hide script and related buttons by default
        self.stc.Hide()
        for w in self.widgets[0]: w.Hide()

        self.SetSizer(self.gbs)
        self.gbs.Layout()
Exemplo n.º 11
0
        def _func(item, row, val_widget_type, item_list_idx, flag_hide):
            col = 0
            ### StaticText of item name
            wn = "%s_sTxt" % (item)
            if len(item) > 18: _txt = item[:18] + ".."
            else: _txt = item
            sTxt = wx.StaticText(self, -1, _txt, name=wn)
            sTxt.SetFont(self.parent.fonts[1])  # small font
            sTxt.SetForegroundColour('#DDDDDD')
            self.gbs.Add(sTxt,
                         pos=(row, col),
                         flag=wx.ALIGN_CENTER_VERTICAL | wx.ALL,
                         border=bw)
            if flag_hide == True: sTxt.Hide()
            vw = 165  # width of a widget (TextCtrl or Choice) for item value
            if item == 'setup_stimuli':
                ### image button to set up stimuli paths and other related information
                wn = "%s_btn" % (item)
                btn = wx.Button(self, -1, label="", name=wn, size=btnSz)
                set_img_for_btn(
                    path.join(self.parent.e_gui_path, "input/img_setup.png"),
                    btn)
                btn.Bind(wx.EVT_LEFT_UP, self.setUpStimuli)
                col += 1
                self.gbs.Add(btn,
                             pos=(row, col),
                             flag=wx.ALIGN_CENTER_VERTICAL | wx.ALL,
                             border=bw)
                if flag_hide == True: btn.Hide()
                vw -= 30
            ### delete button for optional items (item_list_idx == 1)
            if item_list_idx == 1:
                wn = "%s_del_btn" % (item)
                btn = wx.Button(self, -1, "", name=wn, size=btnSz)
                set_img_for_btn(
                    path.join(self.parent.e_gui_path, "input/img_delete.png"),
                    btn)
                btn.Bind(wx.EVT_LEFT_UP, self.onDelItem)
                col += 1
                self.gbs.Add(btn,
                             pos=(row, col),
                             flag=wx.ALIGN_CENTER_VERTICAL | wx.ALL,
                             border=bw)
                if flag_hide == True: btn.Hide()
                vw -= 30
            ### widget for a value of the item
            iData = self.parent.iPanel.item_info[item_list_idx][item]
            if val_widget_type == "choice":
                wn = "%s_cho" % (item)
                valWid = wx.Choice(self,
                                   -1,
                                   choices=[str(x) for x in iData["values"]],
                                   name=wn,
                                   size=(vw, -1))
                valWid.Bind(wx.EVT_CHOICE, self.chkChangedValue)
                idx = valWid.FindString(str(iData["value"]))
                if idx != wx.NOT_FOUND: valWid.SetSelection(idx)
            else:
                wn = "%s_txt" % (item)
                valWid = wx.TextCtrl(self,
                                     -1,
                                     value=str(iData["value"]),
                                     name=wn,
                                     size=(vw, -1),
                                     style=wx.TE_LEFT | wx.TE_PROCESS_ENTER)
                valWid.Bind(wx.EVT_TEXT_ENTER, self.chkChangedValue)
            valWid.SetFont(self.df)
            col += 1
            if item == 'setup_stimuli' or item_list_idx == 1:
                self.gbs.Add(valWid,
                             pos=(row, col),
                             flag=wx.ALIGN_CENTER_VERTICAL | wx.ALL,
                             border=bw)
            else:
                self.gbs.Add(valWid,
                             pos=(row, col),
                             span=(1, 2),
                             flag=wx.ALIGN_CENTER_VERTICAL | wx.ALL,
                             border=bw)
                col += 1
            if flag_hide == True:
                valWid.Hide()
            else:
                self.items[item] = self.getItemVal(item)[
                    1]  # store item and its value
            if item in [
                    'number_of_trials', 'number_of_stimuli_per_trial',
                    'setup_stimuli', 's_type'
            ]:
                valWid.SetEditable(False)
                valWid.SetBackgroundColour('#999999')

            ### marker button
            wn = "%s_marker_btn" % (item)
            btn = wx.Button(self, -1, "", name=wn, size=btnSz)
            set_img_for_btn(
                path.join(self.parent.e_gui_path, "input/img_marker_next.png"),
                btn)
            btn.Bind(wx.EVT_LEFT_UP, self.onDisplayingMarker)
            btn.Hide(
            )  # script is not visible by default, therefore marker (for script) buttons are also hidden by default
            col += 1
            self.gbs.Add(btn,
                         pos=(row, col),
                         flag=wx.ALIGN_CENTER_VERTICAL | wx.ALL,
                         border=bw)
            if flag_hide == True or self.parent.flag_script_visible == False:
                btn.Hide()

            col += 1
            self.gbs.Add(wx.StaticText(self, -1, "", size=(1, 1)),
                         pos=(row, col),
                         flag=wx.EXPAND | wx.ALL,
                         border=bw)
Exemplo n.º 12
0
    def __init__(self, parent, pos, size):
        self.parent = parent
        if DEBUGGING: print('ItemPanel.__init__()')
        sPanel.ScrolledPanel.__init__(self, parent, -1, pos=pos, size=size)

        # basic item list is separated into two groups. [0] = basic; displayed by default, [1] = displayed only when user presses a button
        self.bItemsList = [[
            'setup_stimuli', 'user_response', 'inter_trial_interval',
            'trial_timeout', 'randomize_trials', 'randomize_stimuli'
        ],
                           [
                               'feedback', 'number_of_trials',
                               'number_of_stimuli_per_trial', 'key_bindings',
                               'randomize_stimuli_idx', 'correction_trial',
                               'trigger', 'train_or_test',
                               'reaction_time_start', 'user_response_start'
                           ]]

        self.choice_items = [
            'user_response', 'feedback', 'randomize_trials',
            'randomize_stimuli', 'correction_trial', 'trigger', 'train_or_test'
        ]  # items, whose values will be displayed with wx.Choice widget

        self.item_info = []

        ### basic items (these items are necessary for running experimenter script)
        # it will have item name as key, its value will be another dictionary.
        # the dictionary will have 'values', 'value'(default value) and 'desc'(description)
        # For items with value which will be displayed with wx.Choice, 'values' is a list of choices.
        # For items with value which will be displayed with wx.TextCtrl, 'values' is a list, which has minimum and maximum integer value.
        # For items with wx.TextCtrl and arbitrary string value, 'values' should be None.
        self.item_info.append(
            dict(
                number_of_trials=dict(
                    values=[1, 10000],
                    value=1,
                    desc=
                    "Number of trials.\nThis will be automatically calculated when setup_stimuli is done."
                ),
                number_of_stimuli_per_trial=dict(
                    values=[1, 10000],
                    value=1,
                    desc=
                    "Number of stimuli per trial.\nThis will be automatically calculated when setup_stimuli is done."
                ),
                setup_stimuli=dict(
                    values=None,
                    value="",
                    desc=
                    "By clicking 'setup' (gear shape) button, you will be asked a series of questions related to stimuli path(s) and other information.\n\nStimuli can be divided into several folders or all in one folder.\nIf it is divided into several folders, each folder means a collection of a stimulus file for each trial.\nIf all stimuli files are located in one foler, stimuli filename should have three parts divided by underbar '_'.\nThe 1st part is any string for user's convenience to recognize the file, the 2nd part is a trial index (starting from zero), the 3rd part is a stimulus index (also, starting from zero).\n\nIf filename has '_c' after the stimulus index part, the filename will be treated as a correct response string (When a stimulus is clicked, the filename of the clicked stimulus will be sent as a response string.)\ne.g.) when there are three stimuli, two images and one sound in each trial.\ns_000_00_c.png, s_000_01.png, s_000_02.wav, s_001_00.png, s_001_01_c.png, s_001_02.wav, ...\n\nIf filename has '_c-' at the end, string after '_c-' will be treated as a correct response string.\ne.g.) When there are one image and two text (yes/no), each image stimulus' filename can be as following.\nmyStimulus00_c-yes.png, myStimulus01_c-no.png, myStimulus02_c-no.png, ...\n\nIf neither of them ('_c', or '_c-XXX') is present in filename, the trial will be treated as a trial with no correct response (threfore, no feedback).\n"
                ),
                user_response=dict(
                    values=['mouse_click', 'key_stroke', 'none'],
                    value='mouse_click',
                    desc=
                    "'mouse_click', 'key_stroke', 'none' is available.\n'mouse_click' is used for binding click event to image, text or slider.\n'key_bindings' shoud be set up for 'key_stroke'.\nIf this is 'none' trial finishes when the last stimulus was presentation time is up."
                ),
                key_bindings=dict(
                    values=None,
                    value="['CTRL+Q', 'CTRL+S', 'CTRL+L']",
                    desc=
                    "Should be a python list with string elements in format of 'Modifier key+Target key'\ne.g.) 'CTRL+Q', 'SHIFT+A', 'ALT+C', 'NONE+K', 'NONE+LEFT', 'NONE+F1'.\n\nDefault setup : \nCTRL+Q - quit\nCTRL+S - save session info (result file path, trial_cnt, and trial_idx)\nCTRL_L - load the saved session"
                ),
                feedback=dict(values=['Visual', 'Auditory', 'Both', 'None'],
                              value='Visual',
                              desc="Visual, Auditory, Both, or None"),
                inter_trial_interval=dict(
                    values=[1, 60001],
                    value=1000,
                    desc="Inter-trial-interval in milliseconds."),
                trial_timeout=dict(
                    values=[-1, 60001],
                    value=-1,
                    desc=
                    "Trial timeout time in milliseconds. This time measure will start after 'reaction_time_start'.\n-1 means there's no timeout."
                ),
                randomize_trials=dict(values=[True, False],
                                      value=True,
                                      desc="Randomizing trials sequence."),
                randomize_stimuli=dict(
                    values=[True, False],
                    value=False,
                    desc="Randomzing positions and presenting time."),
                randomize_stimuli_idx=dict(
                    values=None,
                    value=[0],
                    desc=
                    "Normally all stimuli will be randomized. But this list of indices does not include all stimuli indices, stimuli only with these indices will be randomized, while other stimuli will be fixed.\nWhen images and sounds are both used, the sound should be excluded from this index list, because image randomization uses positions of other stimuli, while sound has no positon."
                ),
                correction_trial=dict(
                    values=[True, False],
                    value=False,
                    desc=
                    "The same trial happens repeatedly until correct response."
                ),
                trigger=dict(
                    values=[True, False],
                    value=False,
                    desc=
                    "Trial will start when the trigger image (input/trigger.png) is clicked."
                ),
                train_or_test=dict(
                    values=[True, False],
                    value=False,
                    desc=
                    "Twenty percent of trials will be assigned to 'test' trials, others will be 'training' trials.\nTrials will be randomized regardless of 'randomize_stimuli'.\nThere will be no feedback for test trials.\nThe first trial will be a training trial.\nIf one trial is a test trial, the next one will be a training.\nThese rules and the percentage of test trial can be changed by reprogramming 'make_trial_idx' function in 'start_session' function of 'Experimenter' class in the produced script file."
                ),
                reaction_time_start=dict(
                    values=[0, 360000],
                    value=0,
                    desc=
                    "Time (in milliseconds) to start reaction time measurement.\nReaction time measurement starts after user_response_start. Zero means that reaction time measurement starts at the same time with user_response_start. Minus value is not allowed."
                ),
                user_response_start=dict(
                    values=[-360000, 360000],
                    value=0,
                    desc=
                    "Time (in milliseconds) to start accepting user response.\nDefault value is zero.\nZero here means that user response will be enabled as soon as presentations of all the stimuli are finished. End of stimuli presentation is reached when image is displayed, sound/movie is played to its end, or at user defined time in 'present_time' item.\n\nIf you give minus value here such as -9000 and 10 seconds long movie stimulus is played. User response will be enabled one second after the beginning of the movie.\nIf too large minus value is given (longer than stimulus play), user response will be enabled as soon as trial starts."
                )))

        ### Optional items
        # Dictionary structure is as same as the basic item dictionary
        self.item_info.append(
            dict(arduino=dict(
                values=None,
                value="motor_on",
                desc=
                "When this item is added, script for Arduino will be added.\nWhen the feedback is positive, an activation signal will be sent to Arduino to release food reward.\nThis item's value is the signal text for Arduino chip to activate food reward."
            ), ))

        ### Items for stimulus setup
        # Dictionary structure is as same as the basic item dictionary
        self.item_info.append(
            dict(clickable=dict(
                values=None,
                value=None,
                desc=
                "[This item & its values will automatically appear when the setup_stimuli is done.]\nDetermine whether an image is clickable or not. It will be set to False for 'snd' stimulus."
            ),
                 present_time=dict(
                     values=None,
                     value=None,
                     desc=
                     "[This item & its values will automatically appear when the setup_stimuli is done.]\nPresenting start and end time in milliseconds. The start time starts from one, not zero. When the end time is -1, image stimulus will remain until end of trial, and sound/movie stimulus will play till its end."
                 ),
                 rect=dict(
                     values=None,
                     value=None,
                     desc=
                     "[This item & its values will automatically appear when the setup_stimuli is done.]\nWhen stimulus is image, rect can specify image presentation with x, y, width, height.\nx, y coordinates are float numbers between 0.0 and 1.0.\n0.0 means left or top end, 1.0 means right or bottom end.\nwidth and height are in pixels. If width or height is -1, the image will be displayed with its original size."
                 ),
                 s_type=dict(
                     values=None,
                     value=None,
                     desc=
                     "[This item & its values will automatically appear when the setup_stimuli is done.]\nStimulus type. This is automatically determined by file extensions. Not manually editable."
                 )))

        bd = 0
        self.gbs = wx.GridBagSizer(0, 0)
        self.gbs.Add(wx.StaticLine(self, -1, size=(size[0] - 10, -1)),
                     pos=(0, 0),
                     span=(1, 4),
                     flag=wx.EXPAND | wx.ALL,
                     border=5)
        row = 0
        for i in range(len(self.bItemsList)):
            for item in self.bItemsList[i]:
                row += 1
                wn = "%s_sTxt" % (item)
                sTxt = wx.StaticText(self, -1, item, name=wn)
                sTxt.SetFont(parent.fonts[2])
                sTxt.SetForegroundColour('#DDDDDD')
                self.gbs.Add(sTxt,
                             pos=(row, 0),
                             flag=wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL
                             | wx.ALL,
                             border=0)
                wn = "%s_help_btn" % (item)
                btn = wx.Button(self, -1, "", name=wn, size=(30, 27))
                set_img_for_btn(
                    path.join(self.parent.e_gui_path, "input/img_info.png"),
                    btn)
                btn.Bind(wx.EVT_LEFT_UP, self.onHelp)
                self.gbs.Add(btn,
                             pos=(row, 1),
                             flag=wx.ALIGN_LEFT | wx.ALL,
                             border=1)
                self.gbs.Add((10, -1),
                             pos=(row, 2),
                             flag=wx.ALIGN_LEFT | wx.ALL,
                             border=0)
                self.gbs.Add(wx.StaticText(self, -1, "", size=(1, 1)),
                             pos=(row, 3),
                             flag=wx.EXPAND | wx.ALIGN_LEFT | wx.ALL,
                             border=0)
                if i == 1:  # bItemsList[1] is hidden by default
                    sTxt.Hide()
                    btn.Hide()
            if i == 0:
                row += 1
                self.sh_btn = wx.Button(self,
                                        -1,
                                        "",
                                        name="showHide_btn",
                                        size=(250, 25))
                set_img_for_btn(
                    path.join(self.parent.e_gui_path,
                              "input/img_arrow_down.png"), self.sh_btn)
                self.sh_btn.Bind(wx.EVT_LEFT_UP, self.onShowHide)
                self.flag_bItemsList1_shown = False
                self.gbs.Add(self.sh_btn,
                             pos=(row, 0),
                             span=(1, 4),
                             flag=wx.EXPAND | wx.ALL,
                             border=5)

        for item in sorted(self.item_info[2].keys(
        )):  # items automatically added when stimuli path is selected
            row += 1
            wn = "%s_sTxt" % (item)
            sTxt = wx.StaticText(self, -1, item, name=wn)
            sTxt.SetFont(parent.fonts[2])
            sTxt.SetForegroundColour('#DDDDDD')
            self.gbs.Add(sTxt,
                         pos=(row, 0),
                         flag=wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL
                         | wx.ALL,
                         border=0)
            wn = "%s_help_btn" % (item)
            btn = wx.Button(self, -1, "", name=wn, size=(30, 27))
            set_img_for_btn(
                path.join(self.parent.e_gui_path, "input/img_info.png"), btn)
            btn.Bind(wx.EVT_LEFT_UP, self.onHelp)
            self.gbs.Add(btn,
                         pos=(row, 1),
                         flag=wx.ALIGN_LEFT | wx.ALL,
                         border=1)
            self.gbs.Add((10, -1),
                         pos=(row, 2),
                         flag=wx.ALIGN_LEFT | wx.ALL,
                         border=0)
            self.gbs.Add(wx.StaticText(self, -1, "", size=(1, 1)),
                         pos=(row, 3),
                         flag=wx.EXPAND | wx.ALIGN_LEFT | wx.ALL,
                         border=0)
            sTxt.Hide()
            btn.Hide()

        row += 1
        self.gbs.Add(wx.StaticLine(self, -1, size=(size[0] - 10, -1)),
                     pos=(row, 0),
                     span=(1, 4),
                     flag=wx.EXPAND | wx.ALL,
                     border=5)
        row += 1
        self.gbs.Add(wx.StaticText(self, -1, ""),
                     pos=(row, 0),
                     span=(1, 4),
                     flag=wx.EXPAND | wx.ALL,
                     border=1)
        row += 1
        self.gbs.Add(wx.StaticLine(self, -1, size=(size[0] - 10, -1)),
                     pos=(row, 0),
                     span=(1, 4),
                     flag=wx.EXPAND | wx.ALL,
                     border=5)
        row += 1
        self.sh_op_btn = wx.Button(self,
                                   -1,
                                   "Show optional items",
                                   name="showHideOptionalItems_btn",
                                   size=(250, 25))
        set_img_for_btn(
            path.join(self.parent.e_gui_path, "input/img_arrow_down.png"),
            self.sh_op_btn, False)
        self.sh_op_btn.Bind(wx.EVT_LEFT_UP, self.onShowHideOptionalItems)
        self.flag_optionItems_shown = False
        self.gbs.Add(self.sh_op_btn,
                     pos=(row, 0),
                     span=(1, 4),
                     flag=wx.EXPAND | wx.ALL,
                     border=5)

        for item in sorted(
                self.item_info[1].keys()):  # optional items (arduino, ...)
            row += 1
            wn = "%s_sTxt" % (item)
            sTxt = wx.StaticText(self, -1, item, name=wn)
            sTxt.SetFont(parent.fonts[2])
            sTxt.SetForegroundColour('#DDDDDD')
            self.gbs.Add(sTxt,
                         pos=(row, 0),
                         flag=wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL
                         | wx.ALL,
                         border=0)
            sTxt.Hide()
            wn = "%s_help_btn" % (item)
            btn = wx.Button(self, -1, "", name=wn, size=(30, 27))
            set_img_for_btn(
                path.join(self.parent.e_gui_path, "input/img_info.png"), btn)
            btn.Bind(wx.EVT_LEFT_UP, self.onHelp)
            self.gbs.Add(btn,
                         pos=(row, 1),
                         flag=wx.ALIGN_LEFT | wx.ALL,
                         border=1)
            btn.Hide()
            wn = "%s_add_btn" % (item)
            btn = wx.Button(self, -1, "", name=wn, size=(30, 27))
            set_img_for_btn(
                path.join(self.parent.e_gui_path, "input/img_add.png"), btn)
            btn.Bind(wx.EVT_LEFT_UP, self.onAddItem)
            self.gbs.Add(btn,
                         pos=(row, 2),
                         flag=wx.ALIGN_LEFT | wx.ALL,
                         border=0)
            btn.Hide()
            self.gbs.Add(wx.StaticText(self, -1, "", size=(1, 1)),
                         pos=(row, 3),
                         flag=wx.EXPAND | wx.ALIGN_LEFT | wx.ALL,
                         border=0)
        row += 1
        self.gbs.Add(wx.StaticLine(self, -1, size=(size[0] - 10, -1)),
                     pos=(row, 0),
                     span=(1, 4),
                     flag=wx.EXPAND | wx.ALL,
                     border=5)

        self.SetSizer(self.gbs)
        self.SetupScrolling()