def makoDoServ(self,btn_value,node): murfNode = bt.sib_node(node['id'], self.json, 0) servLog = bt.nameLogfile(node, self.subject, murfNode) self.run = murfNode['run'] # in case of accidental logout self.servProc, self.servOUT, h = lib.doServ(self.subject, self.TabID, self.run, servLog) lib.set_here(node,'disabled', True) return
def enableOnly(j, tab, only=None): """ only: 'first', None """ vBids = visitBids(tab, j) if only == 'first': lib.set_here(btn_node(vBids.pop(0),j),'disabled', False) [lib.set_here(btn_node(bid,j), 'disabled', True) for bid in vBids] return
def enableNext(bid,j): [v,s,p] = bid.split(".") try: nextBtn = btn_node("%s.%s.%d"%(v,s,int(p)+1), j) except LookupError: ## done with this step try: nextBtn = btn_node("%s.%d.%d"%(v,int(s)+1,0), j) except LookupError: ## done with this visit vNode = get_visit(bid,j) lib.set_node(vNode,True, jlib.VCOMPLETE) return int(v)+1 lib.set_here(nextBtn,'disabled', False) return int(v)
def makoRealtimeStim(self, btn_value, node): murfNode = bt.sib_node(node['id'], self.json, 0) stimLog = bt.nameLogfile(node, self.subject, murfNode) self.run = murfNode['run'] ## in case of accidental logout self.flotJavascript() # based on group, use proper stimulus file group = lib.get_node(self.json, j.GROUP) if group == "high": psychofile = j.HIFILE elif group == "low": psychofile = j.LOFILE lib.set_here(node, 'file', psychofile) # record which stimulus file was used # ready to launch! self.stimProc, h = lib.doStim(self.subject, self.TabID, self.run, stimLog, psychofile,self.json["study_info"]["group"]) lib.set_here(node,'disabled', True) # this button only launches. 'End Murfi' cleans up return
def rtDone(j, bid): # Purpose: When an RT run completes, this advances the "progress" key # to the last part of the RT step, so that enableNext can enable the # next step or next visit. # This is a helper function for handling an "End Murfi" buttonpress. Nothing # else should call it. # Inputs: # j (dict) = full json the subject # bid (str) = "x.y.z", as above node = btn_node(bid, j) lib.set_here(node, 'done', True) # disable all sibling parts parent = parent_node(bid, j) for p in range(0, len(parent)): lib.set_here(parent[p], 'disabled', True) # progress is set to button ID of the last part of this step. lastID = lib.get_node(parent, ['-1', 'id']) setProgress(lastID, get_visit(bid, j))
def enableNext(bid, j): [v, s, p] = bid.split(".") try: nextBtn = btn_node("%s.%s.%d" % (v, s, int(p) + 1), j) except LookupError: ## done with this step try: nextBtn = btn_node("%s.%d.%d" % (v, int(s) + 1, 0), j) except LookupError: ## done with this visit vNode = get_visit(bid, j) lib.set_node(vNode, True, jlib.VCOMPLETE) return int(v) + 1 ## we have the next valid button: enable it! ## ... unless we're in redo-mode: skip completed steps until we've resumed resume = lib.get_node(j, jlib.RESUME) if resume: # redo-mode! if compareBids(resume, nextBtn["id"]): # we've caught up to the resume point lib.set_node(j, None, jlib.RESUME) # end redo-mode lib.set_here(nextBtn, "disabled", False) # enable as normal else: # stay in redo-mode if lib.get_node(nextBtn, "time") == "": # not stamped yet, so enable lib.set_here(nextBtn, "disabled", False) else: # timestamped; this was complete before redo began. # don't enable; rather, advance progress & skip to next-next nextID = lib.get_node(nextBtn, "id") setProgress(nextID, get_visit(bid, j)) return enableNext(nextID, j) else: # no redo occurring, normal enable lib.set_here(nextBtn, "disabled", False) return int(v)
def makoMurfiHandler(self, btn_value, node): ## Handle "Start" & "End" differently if ('Start' in btn_value): murfLog = bt.nameLogfile(node, self.subject) try: self.murfProc, self.murfOUT, h = lib.doMurfi(self.subject, self.TabID, self.run, murfLog) except: self.murfProc.kill() self.murfOUT.close() raise lib.set_here(node,'text','End Murfi') ## could do this better lib.set_here(bt.sib_node(node['id'], self.json, 1), "disabled", False) ## activate psychopy #lib.set_here(bt.sib_node(node['id'], self.json, 2), "disabled", False) ## activate servenii elif "End" in btn_value: ## End must also clean up after servenii & rt psychopy, if needed. lib.set_here(bt.sib_node(node['id'], self.json, 1), "disabled", True) ## disable psychopy #lib.set_here(bt.sib_node(node['id'], self.json, 2), "disabled", True) ## disable servenii ## close errant process handles if hasattr(self, 'murfProc'): lib.endMurfi(self.murfProc, self.subject, self.TabID, self.run, self.murfOUT) if hasattr(self, 'stimProc'): self.stimProc.kill() if hasattr(self, 'servProc'): lib.endServ(self.servProc, self.subject, self.TabID, self.run, self.servOUT) lib.set_here(node,'text','Start Murfi') ## check if RT run is done yet: ## -- 150ish TRs collected in results JSON? ==> done; update progress. ## -- otherwise, allow Murfi restart for this run. activeFile = os.path.join(self.visitDir,'data','run00%d_active.json'%self.run) if os.path.exists(activeFile): activeData = lib.load_json(activeFile) print "activeData's length is:", len(activeData['data']) if len(activeData['data']) > 150: bt.rtDone(self.json, node['id']) ## bt.updateProgress gets called in here. else: lib.set_here(node, "disabled", False) ## ensure murfi can be restarted else: print "realtime_app: Can't handle this murfi button value:",btn_value return
def movementRedo(j, tab): ## Use this visit's progress to figure out what things to redo. ## Collaborate with enableNext() to use timestamps as a high-water mark. ## j (dict) = full json for the subject ## tab (int) = visit/session number vNode = get_visit(tab, j) vBids = visitBids(tab, j) ## full, ordered list of all button ids for this visit progress = getProgress(vNode) currentBid = vBids[vBids.index(progress) + 1] ## for current step (after progress) ## 1. build prereq button id list # 1.1 get base prereqs, plus prereqs based on current step's action keyword action = lib.get_node(btn_node(currentBid, j), "action") prereqs = [] for btn in [btn_node(bid, j) for bid in visitBids(tab, j)]: if btn.has_key("prereqFor"): prfor = btn["prereqFor"].split(".") # some prereqs are '.'-joined if ("all" in prfor) or (action in prfor): prereqs.append(btn["id"]) # 1.2 get all siblings of the current step sibs = [lib.get_node(sib, "id") for sib in parent_node(currentBid, j)] prereqs.extend(sibs) # 2. prepare prereqs for redo: clear all tstamps, uncheck checkboxes. for prereq in prereqs: prNode = btn_node(prereq, j) clearTimeStamp(prNode) if lib.get_node(prNode, "action") == "": # it's a checkbox lib.set_here(prNode, "checked", False) # clear checkboxes # 3. save progress to study-wide resume pointer, unless we're restarting a redo. resume = lib.get_node(j, jlib.RESUME) if resume: pass ## restarting redo-mode due to another movement else: ## enter fresh redo-mode lib.set_node(j, progress, jlib.RESUME) # 4. reset progress so that the first prereq is the next thing to happen. vBids.insert(0, "") # if 1st prereq is tab.0.0, then progress = "" (as expected) resetBid = vBids[vBids.index(prereqs[0]) - 1] setProgress(resetBid, vNode) return
def makoDoStim(self,btn_value,node): print btn_value if ('RT' in btn_value): return self.makoRealtimeStim(btn_value,node) else: if ('Launch' in btn_value) or ('Test' in btn_value): psyFile = node['file'] psyArgs = [self.subject, self.TabID, bt.getTimestamp(node)] log = os.path.join(self.visitDir, "%s.log"%btn_value[-1]) print psyFile, psyArgs, log self.stimProc, h = lib.startPsycho(psyFile, psyArgs, log) if ('Launch' in btn_value): lib.set_here(node, 'text', 'End '+ btn_value[-1]) elif ('Test' in btn_value): self.updateProgress(btn_value[0]) elif ('End' in btn_value): ## decide whether to allow restart or to disable! if bt.checkPsychoDone(self.subject, node): self.updateProgress(btn_value[0]) lib.set_here(node,'disabled',True) else: lib.set_here(node, 'text', 'Launch '+ btn_value[-1]) return
def clearTimeStamp(node): lib.set_here(node,'time',"") return
def timeStamp(node): ## store time in epoch-secs + string tStamp = "%f"%time.time() ## get time in seconds in the epoch timeReadable = time.strftime("%H:%M:%S--%m/%d/%Y",time.localtime(float(tStamp))) node['history'].append(tStamp) lib.set_here(node,'time',timeReadable) return ### end timeStamp
def makoCheckboxHandler(self,node): lib.set_here(node, 'checked', True) lib.set_here(node, 'disabled', True) self.updateProgress(node['id']) return
def clearTimeStamp(node): lib.set_here(node, "time", "") return