Example #1
0
    def onRun(self, event):
        if DEBUGGING: print('ScriptPanel.onRun()')
        event.Skip()

        obj = wx.FindWindowByName( "fn", self )
        script_fn = obj.GetValue().strip()
        if path.isfile(script_fn) == False:
            show_msg("File, %s, doesn't exist"%(script_fn))
            return

        f = open(script_fn, 'r')
        fileScript = f.read()
        f.close()
        currScript = self.stc.GetText() # current script in the script panel

        if fileScript != currScript: # script from file and script panel is different
            dlg = PopupDialog(inString="This will run the file, %s.\nThe contents of the file and the current script in this script panel is different.\nPress Okay to overwrite the file with the current script and run.\nPress Cancel to run the file as it is."%(script_fn), title="Overwriting",  size=(400,200), cancel_btn=True)
            result = dlg.ShowModal()
            dlg.Destroy()
            if result == wx.ID_OK: self.onSave(None, flag_overwrite=True) 
        
        cmd = ['pythonw', script_fn]
        stdout = ''
        try:
            p = subprocess.Popen(cmd, stderr=subprocess.STDOUT, stdout=subprocess.PIPE)
            stdout, stderr = p.communicate()
            p.terminate()
            p.wait()
        except:
            pass
        title = "stdout"
        if 'error' in str(stdout).lower(): title += ": ERROR"
        show_msg(msg=stdout.strip(), size=(700,350), title=title)
Example #2
0
    def onSave(self, event, flag_overwrite=False):
        if DEBUGGING: print('ScriptPanel.onSave()')
        if event != None: event.Skip()
        obj = wx.FindWindowByName( "fn", self )
        fn = obj.GetValue().strip()
        if fn == '':
            dlg = wx.MessageDialog(self, 'Filename is empty.', style=wx.OK|wx.ICON_INFORMATION)
            dlg.ShowModal()
            dlg.Destroy()
            return
        savePath = path.join( getcwd(), path.basename(fn) )
        file_exists = path.isfile(savePath)
        if file_exists:
            if flag_overwrite != True: # if it's not already instructed to overwrite
                ### ask whether to overwrite
                dlg = PopupDialog(inString="File already exists. Overwrite it?", size=(300,100), cancel_btn=True)
                result = dlg.ShowModal()
                dlg.Destroy()
                if result == wx.ID_CANCEL: return
        txt = self.stc.GetText()
        f = open(savePath, 'wb')
        f.write(txt.encode('utf8'))
        f.close()

        if txt != self.scriptChangedByMainPanel: # manual script change occurred
            self.updateMainPanelFromScript(txt) # update main panel widgets with the script text, because user might have edited script manually.
            self.scriptChangedByMainPanel = txt

        if not file_exists: show_msg("File is saved at\n%s"%(savePath))
Example #3
0
 def onNavMarkers(self, event):
     if DEBUGGING: print('ScriptPanel.onNavMarkers()')
     if self.markerIds == []:
         show_msg("No markers found.\n(Markers will be added when a marker button is pressed in the center panel or new script lines are added.)", size=(300,170))
         return
    
     if type(event) == str:
         obj_name = event
     else:
         event.Skip()
         obj = event.GetEventObject()
         obj_name = obj.GetName()
     
     ### move screen and caret to the next or prev marker
     if obj_name == 'nextM':
         self.cmi += 1
         if self.cmi >= len(self.markerIds): self.cmi = 0
     elif obj_name == 'prevM':
         self.cmi -= 1
         if self.cmi < 0: self.cmi = len(self.markerIds)-1
     line_num = self.stc.MarkerLineFromHandle(self.markerIds[self.cmi])
     self.stc.GotoLine(line_num)
     #if self.stc.GetLineVisible(line_num) == False: # the line is not visible
     #    vl = max(1, line_num-10)
     #    self.stc.SetFirstVisibleLine(vl)
     self.stc.SetSelection(self.stc.GetCurrentPos(), self.stc.GetLineEndPosition(line_num))
Example #4
0
 def onReplace(self, event):
     ''' search a string in the current script text
     & replace it with the typed text in replaceTxt
     '''
     event.Skip()
     searchTxt, idx1 = self.onSearch(None)
     if idx1 == -1:
         show_msg("The search string, %s, is not found in the current script."%(searchTxt), (250,150))
         return
     evtObjName = event.GetEventObject().GetName() 
     replaceTxt = wx.FindWindowByName("replaceTxt").GetValue().strip()
     if evtObjName == "replaceOneBtn": 
         self.stc.Replace(idx1, idx1+len(searchTxt), replaceTxt)
         self.stc.GotoPos(idx1)
         self.stc.SetSelection(idx1, idx1+len(replaceTxt))
     elif evtObjName == "replaceAllBtn":
         cnt = 1
         lastIdx = -1
         while idx1 != -1:
             self.stc.Replace(idx1, idx1+len(searchTxt), replaceTxt)
             lastIdx = copy(idx1)
             searchTxt, idx1 = self.onSearch(None)
             if idx1 == -1: show_msg("%i found texts are replaced."%(cnt), (250,100))
             cnt += 1
         self.stc.GotoPos(lastIdx)
         self.stc.SetSelection(lastIdx, lastIdx+len(replaceTxt))
         self.stc.SetFocus()
Example #5
0
 def onHelp(self, event):
     ''' show descriptions of a selected item
     '''
     if DEBUGGING: print('ItemPanel.onHelp()')
     obj_name = event.GetEventObject().GetName()
     item = obj_name.replace("_help_btn", "")
     for i in range(len(self.item_info)):
         if item in self.item_info[i].keys():
             show_msg(self.item_info[i][item]["desc"], (400, 250))
             break
Example #6
0
    def onLoad(self, event):
        if DEBUGGING: print('ScriptPanel.onLoad()')
        event.Skip()
        f = wx.FileDialog(self, "Choose a Python file you saved before.", getcwd(), wildcard="Python files (*.py)|*.py", style=wx.FD_DEFAULT_STYLE|wx.FD_OPEN|wx.FD_FILE_MUST_EXIST)
        if f.ShowModal() == wx.ID_CANCEL: return
        fp = f.GetPath()
        f = open(fp, "r")
        txt = f.read()
        f.close()
        if (not 'class Experimenter' in txt) or (not '#[flag:' in txt):
            show_msg("The chosen file is not an Experimenter Python file.")
            return
        
        self.updateMainPanelFromScript(txt) # update main panel widgets with the script text

        self.stc.SetText(txt) # load the script text to STC
        self.stc.SetFirstVisibleLine(0)
        self.stc.ScrollToColumn(0)
Example #7
0
    def onCheck(self, event):
        ''' Fisnish_setup button is clicked.
        Process some check-up procedures.
        '''
        if DEBUGGING: print('SetupStimuliDialog.onCheck()')

        rv = self.return_val
        if rv["number_of_trials"] == 0 or rv[
                "number_of_experimental_stimuli"] + rv[
                    "number_of_response_stimuli"] == 0:
            show_msg(
                "'Number of trials' should be greater than zero and there should be, at least, one stimulus."
            )
            return

        if 'mov' in rv["types_of_es"]:
            rslt = self.query("movie_module", (300, 300))
            if rslt == None: return
            rv["movie_module"] = rslt

        ### if response stimulus (such as 'yes/no' string) is only one (meaning the same string will be used for all trials)
        ### make it for the number of trials. e.g.) ['yes']*3 ---> ['yes', 'yes', 'yes'] (when number_of_trials == 3)
        if rv["number_of_trials"] > 1:
            for pi in range(len(rv["paths_of_rs"])):
                if len(rv["paths_of_rs"][pi]) == 1:
                    rv["paths_of_rs"][
                        pi] = rv["paths_of_rs"][pi] * rv["number_of_trials"]

        if self.rsCorrIdx != -1:  # there is an index indicating a folder with correct responses
            if rv["types_of_rs"][self.rsCorrIdx] != "txt":
                ### add the correct response tag, "_c", at the end of filename
                for f in rv["paths_of_rs"][self.rsCorrIdx]:
                    bn = path.basename(f)
                    ext = bn.split(".")[-1]
                    new_bn = bn.replace("." + ext, "")
                    if (new_bn[-2:] == "_c") or ("_c-" in new_bn):
                        continue  # filename already has the correct response tag
                    new_bn = new_bn + "_c." + ext
                    new_f = f.replace(bn, new_bn)
                    rename(f, new_f)
                    rv["paths_of_rs"] = new_f
        event.Skip()
Example #8
0
 def onSearch(self, event):
     ''' search a string in the current script text
     '''
     if event != None: event.Skip()
     searchTxt = wx.FindWindowByName("searchTxt").GetValue().strip()
     if searchTxt == '':
         if event == None: return searchTxt, -1
         else: return
     curr_pos = self.stc.GetCurrentPos()
     if curr_pos > 0: curr_pos += len(searchTxt)
     txtLen = self.stc.GetTextLength()
     if curr_pos >= txtLen:
         idx = self.stc.FindText(0, txtLen, searchTxt )
     else:
         idx = self.stc.FindText(curr_pos, txtLen, searchTxt )
         if idx == -1: idx = self.stc.FindText(0, txtLen, searchTxt )
     if event == None: return searchTxt, idx # if this function was called by 'onReplace', return found index
     if idx == -1:
         show_msg("The search string, %s, is not found in the current script."%(searchTxt), (250,150))
     else:
         self.stc.GotoPos(idx)
         self.stc.SetSelection(idx, idx+len(searchTxt))
Example #9
0
    def onRectTextChange(self, event):
        ''' apply manually changed stimulus rect 
        '''
        if DEBUGGING: print('SetupStimuliDialog.onRectTextChange()')

        obj = event.GetEventObject()
        objName = obj.GetName()
        val = obj.GetValue().strip('[]')
        r = val.split(",")
        if len(r) != 4: return
        try:
            r[0] = float(r[0])
            r[1] = float(r[1])
            r[2] = int(r[2])
            r[3] = int(r[3])
        except:
            show_msg("Invalid number")
            return
        if r[0] < 0.0 or r[0] > 1.0 or r[1] < 0.0 or r[1] > 1.0:
            show_msg("Invalid x/y")
            return
        if r[2] < -1 or r[2] == 0 or r[3] < -1 or r[3] == 0:
            show_msg("Invalid width/height")
            return
        if r[3] == -1: hh = self.ds_sz[1]
        else: hh = r[3] / 2
        pos = (int(self.w_sz[0] * r[0]) - obj.GetSize()[0] / 2,
               int(self.w_sz[1] * r[1]) + hh / 2 + 5)
        obj.SetPosition(pos)
        btn = wx.FindWindowByName(objName.replace("_rect_", "_open_btn_"),
                                  self)
        pos = (int(self.w_sz[0] * r[0]) - btn.GetSize()[0] / 2,
               int(self.w_sz[1] * r[1]) - btn.GetSize()[1] / 2 -
               self.ds_sz[1] / 2)
        btn.SetPosition(pos)
        if objName.startswith('rs'):  # response stimulus rect
            btn = wx.FindWindowByName(
                objName.replace("_rect_", "_correct_btn_"), self)
            pos = (int(self.w_sz[0] * r[0]) + self.ds_sz[0] / 2 -
                   btn.GetSize()[0], int(self.w_sz[1] * r[1]) -
                   btn.GetSize()[1] / 2 - self.ds_sz[1] / 2)
            btn.SetPosition(pos)
        idx = int(objName.split("_")[-1])
        if objName.startswith('es_'): self.return_val["rects_of_es"][idx] = r
        elif objName.startswith('rs_'): self.return_val["rects_of_rs"][idx] = r
        self.Refresh()
Example #10
0
    def onSelectStim(self, event):
        ''' select and set up stimuli (selecting folder, entering texts, choosing slider, choosing correct response, etc)
        '''
        if DEBUGGING: print('SetupStimuliDialog.onSelectStim()')

        obj = event.GetEventObject()
        objName = obj.GetName()

        ss = objName.split("_")
        sTag = ss[0]  # es (experimental stimuli) or rs (response stimuli)
        sIdx = int(ss[-1])
        tKey = "types_of_%s" % (sTag)
        pKey = "paths_of_%s" % (sTag)
        rKey = "rects_of_%s" % (sTag)

        if sTag == "rs" and self.sliders[sIdx] != None:
            self.sliders[sIdx].Destroy()
            self.sliders[sIdx] = None

        type_of_stim = self.query("type_of_stim", (350, 150), sTag)
        if type_of_stim == None:
            return
        elif type_of_stim == "text":
            ### enter text stimuli
            txt_stim = self.query("text_stim", (500, 350))
            if txt_stim == None: return
            txt_stim = [x.strip() for x in txt_stim.split(",")]
            if len(txt_stim) != 1 and len(
                    txt_stim) != self.return_val["number_of_trials"]:
                show_msg(
                    "Number of stimuli should match with 'Number of trials' you entered. (Or one in case the same stimulus is used for all trials)."
                )
                return
            self.return_val[tKey][sIdx] = "txt"
            self.return_val[pKey][sIdx] = txt_stim

        elif type_of_stim == "slider":
            self.return_val[tKey][sIdx] = "slider"
            self.return_val[pKey][sIdx] = ["slider"]
            r = self.return_val[rKey][sIdx]
            w = r[2]
            if w == -1: w = 300
            self.sliders[sIdx] = wx.Slider(self,
                                           -1,
                                           5,
                                           0,
                                           10,
                                           pos=(1, 1),
                                           size=(w, -1),
                                           style=wx.SL_HORIZONTAL
                                           | wx.SL_AUTOTICKS)
            x = r[0] * self.parent.parent.w_sz[0] - w / 2
            y = r[1] * self.parent.parent.w_sz[0] - self.sliders[sIdx].GetSize(
            )[1] / 2
            self.sliders[sIdx].SetPosition((x, y))
            rt = [
                x.strip() for x in self.rsRectTxts[sIdx].GetValue().strip(
                    "[]").split(",")
            ]
            self.rsRectTxts[sIdx].SetValue("[%s, %s, %i, %s]" %
                                           (rt[0], rt[1], w, rt[3]))
            self.return_val[rKey][sIdx] = [
                float(rt[0]), float(rt[1]), w,
                int(rt[3])
            ]

        else:  # image
            ### choose a folder, containing stimuli files for this stimulus
            dlg = wx.DirDialog(self, "Choose a folder for this stimulus.",
                               self.e_gui_path,
                               wx.DD_DEFAULT_STYLE | wx.DD_DIR_MUST_EXIST)
            if dlg.ShowModal() == wx.ID_CANCEL: return
            cnt = [0, 0, 0]  # img, snd, mov
            cnt_lbl = ["img", "snd", "mov"]
            sfp = []  # stimuli file path
            fl = sorted(glob(path.join(dlg.GetPath(), "*.*")))
            for f in fl:
                ext = path.basename(f).split('.')[-1]
                if ext in self.parent.parent.allowed_img_ext: cnt[0] += 1
                elif ext in self.parent.parent.allowed_snd_ext: cnt[1] += 1
                elif ext in self.parent.parent.allowed_mov_ext: cnt[2] += 1
            if sum(cnt) == 0:
                show_msg(
                    "No stimuli files is recognized in the selected folder.")
                return
            max_cnt = max(cnt)
            if max_cnt != 1 and max_cnt != self.return_val["number_of_trials"]:
                show_msg(
                    "Number of stimuli should match with 'Number of trials' you entered. (Or one in case the same stimulus is used for all trials)."
                )
                return
            st = cnt_lbl[cnt.index(max_cnt)]  # stimulus type
            if sTag == "rs" and st != 'img':
                show_msg(
                    "Response stimulus could be image, text, or slider. Sound or movie is not allowed."
                )
                return
            if st == "img": allowed_ext = self.parent.parent.allowed_img_ext
            elif st == "snd": allowed_ext = self.parent.parent.allowed_snd_ext
            elif st == "mov": allowed_ext = self.parent.parent.allowed_mov_ext
            for f in fl:
                ext = path.basename(f).split('.')[-1]
                if ext in allowed_ext: sfp.append(f)
            self.return_val[tKey][sIdx] = st
            self.return_val[pKey][sIdx] = sfp
            tName = "%s_rect_%i" % (sTag, sIdx)
            rectObj = wx.FindWindowByName(tName, self)
            if st == "snd": rectObj.Disable()
            else: rectObj.Enable()

        if type_of_stim == "image": self.rsCorrectBtns[sIdx].Show()
        else: self.rsCorrectBtns[sIdx].Hide()

        self.Refresh()
Example #11
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()
Example #12
0
 def updateMainPanelFromScript(self, txt):
     ''' Update main panel widgets with contents from script, when laoding script from file or saving occurs.
     'txt': script text
     '''
     ### delete (hide from screen) current optional item widgets in main-panel 
     for item in self.parent.iPanel.item_info[1]:
         btn_name = "%s_del_btn"%(item)
         del_btn_obj = wx.FindWindowByName( btn_name, self.parent.mPanel )
         if del_btn_obj != None: # object found
             self.parent.mPanel.onDelItem(btn_name) # delete
     
     ### update or add items in main-panel with the loaded script 
     # basic items
     err_msg = ""
     for item in sorted(self.parent.iPanel.item_info[0].keys()): # iterate basic items
         idx1 = txt.find("#[flag:%s]"%(item))
         if idx1 == -1: # flag was not found
             err_msg += "#[flag:%s] was not found.\n"%(item)
             continue
         idx2 = copy(idx1)
         while txt[idx1] != '=': idx1 -= 1 # move index to the previous '=' sign
         val = txt[idx1+1:idx2].strip().replace('\n','').replace(' ','')
         if val[0] != '[' and val[-1] != ']': # it's not a list
             if '"' in val: val = val.replace('"', '') # get rid of double quote marks
             if "'" in val: val = val.replace("'", '') # get rid of single quote marks 
         self.parent.mPanel.setItemVal(item, val)
     if err_msg != "": err_msg += "\n\n"
     # stimulus items
     _list = list(self.parent.iPanel.item_info[2].keys())
     _list.remove('s_type')
     _list.insert(0, 's_type') # s_type;stimulus-type should be processed first, because others (clickable, etc) refers s_type's values
     for item in _list: # iterate stimulus items
         idx1 = txt.find("#[flag:%s]"%(item))
         if idx1 == -1: # flag was not found
             err_msg += "#[flag:%s] was not found.\n"%(item)
             continue
         idx2 = copy(idx1)
         while txt[idx1] != '=': idx1 -= 1 # move index to the previous '=' sign
         val = txt[idx1+1:idx2].strip().replace('\n','').replace(' ','')
         self.parent.mPanel.add_del_item(item, item_list_idx=2)
         self.parent.mPanel.setItemVal(item, val)
     if err_msg != "": err_msg += "\n\n"
     # optional items
     for item in sorted(self.parent.iPanel.item_info[1].keys()): # iterate optional items
         idx1 = txt.find("#[flag:%s]"%(item))
         if idx1 == -1: continue # continue, if the flag was not found.
         idx2 = copy(idx1)
         while txt[idx1] != '=': idx1 -= 1 # move index to the previous '=' sign
         val = txt[idx1+1:idx2].strip().replace('\n','').replace(' ','')
         if val == 'False': continue
         if val[0] != '[' and val[-1] != ']': # it's not a list
             if '"' in val: val = val.replace('"', '') # get rid of double quote marks
             if "'" in val: val = val.replace("'", '') # get rid of single quote marks 
         self.parent.mPanel.add_del_item(item, item_list_idx=1)
         self.parent.mPanel.setItemVal(item, val)
     if err_msg != "": show_msg(err_msg)
     # audio_output
     idx = txt.find("class Output_AudioData")
     if idx != -1: # the class was found
         self.parent.mPanel.items['audio_output'] = "added"
     # movie
     idx = txt.find("class MovPlayer")
     if idx != -1: # the class was found
         self.parent.mPanel.items['movie'] = "added"
Example #13
0
    def chkChangedValue(self, event):
        if DEBUGGING: print('MainPanel.chkChangedValue()')
        '''Check & process (such as showing error message, updating the script, etc) the entered value
        When the value was changed by SetValue by code, 'event' will be name of the object(widget)
        '''
        if type(event) == str:
            obj_name = event
            obj = wx.FindWindowByName(obj_name, self)
        else:
            event.Skip()
            obj = event.GetEventObject()
            obj_name = obj.GetName()
        item = obj_name[:-4]

        if '_txt' in obj_name:
            vType, val = self.getItemVal(item)
            key_found_in_item_info = False
            for ii in range(len(self.parent.iPanel.item_info)):
                iInfo = self.parent.iPanel.item_info[ii]
                if item in iInfo.keys():
                    key_found_in_item_info = True
                    break

            err_msg = ""

            ### check whether the entered value is in the range of values, where it's applicable
            if key_found_in_item_info == True and iInfo[item]["values"] != None:
                rng = iInfo[item]["values"]  # range of values
                err_msg = ""
                _val = None
                try:
                    _val = int(val)
                except:
                    pass
                if _val == None:
                    err_msg += "This value should be an integer.\n"
                else:
                    if rng[0] > _val or rng[1] < _val:
                        err_msg += "This value should range between %i and %i\n" % (
                            rng[0], rng[1])

            if item in ['clickable', 'rect']:
                stObj = wx.FindWindowByName("s_type_txt", self)
                st = stObj.GetValue().replace(' ', '').strip("[]").replace(
                    '"', '').replace("'", "").split(",")  # stimulus types
            if item == 'clickable':
                ### check values of clickable
                val = re.sub(
                    '(?i)' + re.escape('true'), 'True', val
                )  # change 'true' with lower or upper case on any letter to 'True' for boolean value
                val = re.sub(
                    '(?i)' + re.escape('false'), 'False', val
                )  # change 'false' with lower or upper case on any letter to 'False' for boolean value
                obj.SetValue(val)
                _val = val.strip().strip("[]").split(",")
                ur = self.getItemVal("user_response")[1]
                for i in range(len(_val)):
                    if _val[i].strip().lower(
                    ) == "true" and ur != 'mouse_click':
                        err_msg += "Item index %i in 'clickable': user_response is not mouse_click.\n" % (
                            i)
                    if _val[i].strip().lower() == "true" and st[i].strip(
                    ) == "snd":
                        err_msg += "Item index %i in 'clickable': 'snd' stimulus can't be clicked.\n" % (
                            i)
            elif item == 'present_time':
                ### check values of 'present_time'
                _val = val.replace(" ", "").strip("[]").split(
                    "],[")  # split by stimulus
                for i in range(len(_val)):
                    _v = _val[i].split(
                        ",")  # split the start-time and end-time
                    if len(_v) != 2:
                        err_msg += "Item index %i in 'present_time': Length of an inside list of 'present_time' should be two, start-time & end-time.\n" % (
                            i)
                    else:
                        for j in range(2):
                            try:
                                _v[j] = int(_v[j])
                            except:
                                pass
                        if type(_v[0]) != int or type(_v[1]) != int:
                            err_msg += "Item index %i in 'present_time': Items in 'present_time' should be integers (time in milliseconds).\n" % (
                                i)
                        else:
                            if _v[0] < 1:
                                err_msg += "Item index %i in 'present_time': Start-time, (first item in the inner list), should be one at minimum.\n" % (
                                    i)
                            if _v[1] != -1 and _v[1] <= _v[
                                    0]:  # End-time should be either -1 or larger than the start-time.
                                err_msg += "Item index %i in 'present_time': End-time, (second item in the inner list), should be larger than the start-time.\n" % (
                                    i)
            elif item == 'rect':
                ### check values of 'rect'
                val = re.sub(
                    '(?i)' + re.escape('none'), 'None', val
                )  # change 'none' with lower or upper case on any letter to 'None'
                obj.SetValue(val)
                _val = val.replace(" ", "").strip("[]").split(
                    "],[")  # split by stimulus
                for i in range(len(_val)):
                    _v = _val[i].split(",")  # split rect info (x,y,w,h)
                    if len(_v) != 4:
                        err_msg += "Item index %i in 'rect': Length of an inside list of 'rect' should be four (x,y,w,h).\n" % (
                            i)
                        continue
                    if st[i].strip() == 'snd':
                        if _val[i] != "None,None,None,None":
                            err_msg += "Item index %i in 'rect': 'rect' is not applicable for 'snd' stimulus. It should be None,None,None,None.\n" % (
                                i)
                            continue
                    else:
                        try:
                            _v[0] = float(_v[0])
                            _v[1] = float(_v[1])
                            _v[2] = int(_v[2])
                            _v[3] = int(_v[3])
                        except:
                            pass
                        for j in range(len(_v)):
                            if j < 2 and type(_v[j]) != float:
                                err_msg += "x & y coordiantes in 'rect' should be float numbers.\nCheck more info by clicking (i) button next to 'rect' in the lfet panel.\n"
                            elif j >= 2 and type(_v[j]) != int:
                                err_msg += "width & height in 'rect' should be integers.\nCheck more info by clicking (i) button next to 'rect' in the lfet panel.\n"
                            else:
                                if j < 2:  # x, y
                                    if _v[j] < 0 or _v[
                                            j] > 1:  # x, y should between 0.0 and 1.0
                                        err_msg += "x & y in 'rect' should be between 0.0 and 1.0.\nCheck more info by clicking (i) button next to 'rect' in the left panel.\n"
                                else:  # w, h
                                    if _v[j] != -1 and _v[
                                            j] <= 0:  # w, h should be -1 or larger than zero
                                        err_msg += "width & height in 'rect' should be larger than zero.\nCheck more info by clicking (i) button next to 'rect' in the left panel.\n"
                                if err_msg != "": break

            if err_msg != "":
                show_msg(err_msg, size=(700, 350))
                obj.SetValue(
                    str(self.items[item]
                        ))  # return the value to the previously stored value
                return

        elif '_cho' in obj_name:
            vType, val = self.getItemVal(item)
            if item == 'feedback':
                if val in ['Auditory', 'Both']:
                    self.addItemScript('audio_output')
                    self.items['audio_output'] = "added"
                else:
                    self.removeItemScript('audio_output')
                    __ = self.items.pop('audio_output', None)

            elif item == 'user_response':
                obj = wx.FindWindowByName("clickable_txt")
                if obj != None:
                    if val == 'mouse_click':
                        obj.SetEditable(True)
                        obj.SetBackgroundColour('#ffffff')
                    else:
                        ### if user_response is not mouse_click, clickable should be all False
                        ns = int(
                            self.getItemVal("number_of_stimuli_per_trial")[1])
                        _v = str([False for x in range(ns)])
                        self.setItemVal("clickable", _v)
                        obj.SetEditable(False)
                        obj.SetBackgroundColour('#999999')

        self.parent.sPanel.updateItemVal(item)
        self.items[item] = val  # store item's value

        if item == 'user_response' and val == 'key_stroke':
            msg = "For key_stroke to work, some programming is necessary.\n\nFirst, add desired keys to key_bindings.\ne.g.) To process key stroke of 'A' and 'L', add 'NONE+A, NONE+L' in key_bindings.\n\nNext, you should program how to deal with correct user response. The user response will be 'A' or 'L' in case of the above example. Which will be correct in which trial is determined in init_expmt function.\nMarkers for key_stroke related lines in the script will be shown after you close this window."
            show_msg(msg, size=(500, 300))
            self.parent.sPanel.dispMarkers("key_stroke")