def shortestDistanceFromWall(self, point): '''returns the shortest distance of the point to a maze wall in degrees''' from psychopy.event import xydist point-=self.pos X=Maze.I; Y = Maze.J (gx,gy)=self.dispSize/2.0 arena=(((-gx,-gy),(gx,-gy)), ((gx,-gy),(gx,gy)), ((-gx,gy),(gx,gy)),((-gx,gy),(-gx,-gy))) # check outside walls dists=(abs(point[Y]+gy), abs(-point[X]+gx), abs(-point[Y]+gy),abs(point[X]+gx)) shd = min(dists) edge=arena[dists.index(shd)] # check the lines for line in self.lineXY: dim=int(line[1][X]==line[0][X]) # 1 is vertical mx=int(line[0][dim]<line[1][dim]) mn=1-mx if point[dim]>line[mx][dim]: d=xydist(point,line[mx]) ol=line[mx] elif point[dim]<line[mn][dim]: d=xydist(point,line[mn]) ol=line[mn] else: d=abs(point[1-dim]-line[0][1-dim]) ol=line if d<shd: shd=d; edge=ol #print shd,point, edge return shd-self.lw/2.0, edge
def circleLine(p0,lin1,lin2,r): """ compute circle line intersetion p0 - circle center lin1, lin2 - line edges r - circle radius """ # translate first p2=lin2-p0; p1=lin1-p0 dpos=p2-p1 dr=dpos[X]**2+dpos[Y]**2 det=p1[X]*p2[Y]-p1[Y]*p2[X] discriminant= dr*r**2-det**2 if discriminant<0: raise NameError('No intersection') temp1=(2*bool(dpos[Y]>=0)-1)*dpos[X]*discriminant**0.5 temp2=abs(dpos[Y])*discriminant**0.5 inter=(((det*dpos[Y]+temp1)/dr, (-det*dpos[X]+temp2)/dr), ((det*dpos[Y]-temp1)/dr, (-det*dpos[X]-temp2)/dr)) # output point which is nearer to p1 i= (xydist(p1,inter[0])+xydist(p2,inter[0]) > xydist(p1,inter[1])+xydist(p2,inter[1])) # check whether inter lies between line edges cw=xydist(p1,p2) if xydist(p1,inter[i])>=cw or xydist(p2,inter[i])>=cw: raise NameError('Intersection out of bounds') return np.array(inter[i])+p0
def getJudgment(self,giveFeedback=False): '''asks subject to select chaser chasee''' position=np.transpose(self.pos) cond=position.shape[1] self.mouse.clickReset();self.mouse.setVisible(1) elem=self.elem t0=core.getTime();selected=[] mkey=self.mouse.getPressed() lastPress=t0 while sum(mkey)>0: elem.draw() self.wind.flip() mkey=self.mouse.getPressed() released=True clrs=np.ones((cond,1))*Q.agentCLR while len(selected) <2: elem.draw() self.wind.flip() mpos=self.mouse.getPos() mkey=self.mouse.getPressed() mtime=core.getTime() for a in range(cond): if (event.xydist(mpos,np.squeeze(position[:,a])) < Q.agentRadius*self.scale): if 0<sum(mkey) and released: # button pressed if selected.count(a)==0: # avoid selecting twice clrs[a]=Q.selectedCLR elem.setColors(clrs,'rgb') selected.append(a) self.output.write('\t%d\t%2.4f' % (a,mtime-t0)) released=False elif a in selected: # no button pressed but selected already clrs[a]=Q.selectedCLR elem.setColors(clrs,'rgb') else: # no button pressed but mouse cursor over agent clrs[a]=Q.mouseoverCLR elem.setColors(clrs,'rgb') elif a in selected: # no button pressed, no cursor over agent, but already selected clrs[a]=Q.selectedCLR elem.setColors(clrs,'rgb') else: # no button press, no cursor over agent, not selected clrs[a]=Q.agentCLR elem.setColors(clrs,'rgb') if 0==sum(mkey) and not released: released=True t0=core.getTime() while core.getTime()-t0<1: elem.draw() self.wind.flip() self.mouse.setVisible(0) if (selected[0]==0 and selected[1]==1 or selected[0]==1 and selected[1]==0): return 1 else: return 0
def draw(self, debug_mode=False): mouse_x, mouse_y = self.mouse.getPos() for text_stim in self.contrib_choices: if xydist((mouse_x, mouse_y), text_stim.pos) < self.mouseover_threshold: text_stim.color = 'darkorange' if self.mouse.getPressed()[0]: self.contrib_choice = text_stim.text self.contrib_instructions.setText(self.instr_text_preformat.format(self.contrib_choice)) self.continue_button.clickable = True else: text_stim.color = 'white' text_stim.draw() self.continue_button.draw() self.contrib_instructions.draw() if self.gaze_pos_getter is not None: self.gaze.pos = self.coords(self.gaze_pos_getter()) self.gaze.draw()
def test_xydist(self): assert event.xydist([0,0], [1,1]) == np.sqrt(2)
def test_misc(self): assert event.xydist([0, 0], [1, 1]) == sqrt(2)
def test_misc(self): assert event.xydist([0,0], [1,1]) == sqrt(2)
def generateTrial(nragents,maze,rejectionDistance=0.0,STATISTICS=False): ''' generates the agent trajectories for a single trial the generation may take considerably longer when rejectionDistance>0 nragents - number of agents to generate maze - Maze class instance (see Maze.py) rejectionDistance - chaser-chasee minimum distance in degrees STATISTICS - if True will log stats for the Diagnosis class returns ndarray of size (nrframes x nragents x 3) first dim - number of frames is derived based on trial duration and frame rate (both in Settings.py) second dim - the first agents is chasee, the second agents is chaser, the rest are distractors third dim - X position in degrees, Y position in degrees, direction in radians if STATISTICS is True returns statistics ''' if STATISTICS: nrbacktracks=0 # init chaser chasee chasee=RandomAgent(Q.nrframes,maze.dispSize,maze.pos, Q.pDirChange[CHASEE],Q.aSpeed,Q.phiRange[0]) chaser=HeatSeekingChaser(Q.nrframes,maze.dispSize,maze.pos, Q.pDirChange[CHASER],Q.aSpeed,Q.phiRange[CHASER],True) while (xydist(chaser.getPosition(),chasee.getPosition())<Q.initDistCC[MIN] and xydist(chaser.getPosition(),chasee.getPosition())>Q.initDistCC[MAX]): # resample until valid distance between chaser and chasee is obtained chasee.reset(); chaser.reset() agents=[chasee,chaser] # init distractors for d in range(nragents-2): distractor=RandomAgent(Q.nrframes,maze.dispSize,maze.pos, Q.pDirChange[DISTRACTOR],Q.aSpeed,Q.phiRange[CHASEE]) agents.append(distractor) # check for wall collisions for a in range(nragents): d,edge=maze.shortestDistanceFromWall(agents[a].getPosition()) while d<=Q.agentRadius: agents[a].reset() d,edge=maze.shortestDistanceFromWall(agents[a].getPosition()) # generate the movement of chasee and chaser finished=False while not finished: # check the distance (dx,dy)=chasee.getPosition() - chaser.getPosition() if np.sqrt(dx**2+dy**2)<rejectionDistance: if STATISTICS: nrbacktracks+=1 deadend=chaser.backtrack() chasee.backtrack() if deadend: # reset the algorithm print 'dead end', chasee.f if STATISTICS: return None, None, None, None,None else: return None (dx,dy)=chasee.getPosition() - chaser.getPosition() # move chaser and avoid walls chaser.move((dx,dy)) d,edge=maze.shortestDistanceFromWall(chaser.getPosition()) if d<=Q.agentRadius: newD=maze.bounceOff(chaser.getPosition(), chaser.getPosition(-1),edge,Q.agentRadius) chaser.crashed(newD=newD,targetPos=(dx,dy)) # move chasee and avoid walls finished=chasee.move() d,edge=maze.shortestDistanceFromWall(chasee.getPosition()) if d<=Q.agentRadius: newD=maze.bounceOff(chasee.getPosition(), chasee.getPosition(-1),edge,Q.agentRadius) chasee.crashed(newD) #if chaser.f>401: # raise NameError('stop') # generate distractor movement finished=False while not finished and nragents>2: for a in range(2,nragents): finished=agents[a].move() d,edge=maze.shortestDistanceFromWall(agents[a].getPosition()) if d<=Q.agentRadius: newD=maze.bounceOff(agents[a].getPosition(), agents[a].getPosition(-1),edge,Q.agentRadius) agents[a].crashed(newD) trajectories=np.zeros((Q.nrframes,nragents,3)) for a in range(nragents): tt=agents[a].getTrajectory() trajectories[:,a,X]=tt[:,X] trajectories[:,a,Y]=tt[:,Y] trajectories[:,a,PHI]=tt[:,PHI] if STATISTICS: #statistics=np.zeros((nrframes,nragents,3)) statistics=[trajectories,np.zeros((Q.nrframes,3)), np.zeros((3)),nrbacktracks,[chasee.ndc.sum(),chaser.ndc.sum(),agents[2].ndc.sum()]] for a in range(3): statistics[1][:,a]=agents[a].getTrajectory()[:,PHI] statistics[2][a]=agents[a].nrcrashes.sum() return statistics else: return trajectories
def inStim(pointer, target): pos1 = pointer.getPos() pos2 = target.pos return (event.xydist(pos1, pos2) < 0.05)