lum_text = visual.TextBox(window=win, text=(str(lum_val)), font_size=fontSize, font_color=fontClr, pos=(-2690, 475), size=(300, 37), units='pix', grid_horz_justification='center', grid_vert_justification='center') #draw grating and lum val DrawTexture.draw() lum_text.draw() #flip window and display gratting and lum val win.flip() mouse = event.Mouse(visible=True, win=win) #display grating; and allow user to modify luminance of the grating according to right and left clic while True: core.wait(0.1) #get keys currMouse = mouse.getPressed() #clicking the middle button causes program to close if currMouse[1]: break #left clic: increase lum
def drumgrating(SpatFreqDeg, TempFreq, t_before, t_During, t_after, Synch, Motionmode): #any paramter potentially changed by user in front.py from psychopy import visual from psychopy import event from psychopy import clock from win32api import GetSystemMetrics from init_para import (drumgrating_addblank, drumgrating_Amp_sinu, drumgrating_controlmod, drumgrating_dirindex, drumgrating_Ori, drumgrating_parasize, drumgrating_t_triginit, drumgrating_GammaFactor, drumgrating_AmpFactor, drumgrating_contrast, drumgrating_MeanLum, winWidth , winHeight, ScrnNum, PixelSize, winWidthofEachDisp, DisplayFrameWidth, FR, square1, square2, fontSize, fontClr, win, Local_IP, Local_Port, Remote_IP, Remote_Port) import socket import numpy as np import conv #crating mouse functionality mouse = event.Mouse( visible = True, win = win ) if Synch: #creating the socket in which communications will take place sock = socket.socket( socket.AF_INET, socket.SOCK_DGRAM ) #binding the local IP address and local port sock.bind((Local_IP, Local_Port)) #creating textbox showing that this VS computer is waiting for UDP signal standBy= visual.TextBox( window=win, text=("Waiting for starting the control computer."), font_size = fontSize, font_color=fontClr, pos=(-2690 ,475), size=(300,37), units='pix', grid_horz_justification='center', grid_vert_justification='center') standBy.draw() square1.draw() square2.draw() win.flip() try: #wait for the command 'gammacorrection' info = sock.recv(1024) except Exception: sock.close() print("Did not recieve info, connection timeout.") return #sending 'gammafloatampfloat' to the second PC sock.sendto(("gamma" + str(drumgrating_GammaFactor) + "amp" + str(drumgrating_AmpFactor)), (Remote_IP, Remote_Port)) #creating textbox showing that this VS computer is waiting for UDP signal standBy= visual.TextBox( window=win, text=("Control Computer is Ready."), font_size = fontSize, font_color=fontClr, pos=(-2690 ,475), size=(300,37), units='pix', grid_horz_justification='center', grid_vert_justification='center') standBy.draw() try: #waiting for the signal autoVs drumgrating_controlmod = sock.recv(1024) except Exception: sock.close() print("Did not recieve drumgrating_controlmod, connection timeout.") return #sending 'Wait for parameters' to the second PC sock.sendto("Wait for parameters", (Remote_IP, Remote_Port)) if drumgrating_controlmod == 'autoVS': try: drumgrating_parasize = sock.recv(1024) except Exception: sock.close() print("Did not recieve parasize, connection timeout.") return #sending a completion transcript sock.sendto("read parasize", (Remote_IP, Remote_Port)) #converting the string recieved into int drumgrating_parasize = conv.deleteParasize(drumgrating_parasize) #making the array in which the parameters will be added to paras = np.empty(shape=[drumgrating_parasize, 9]) #adding the parameters to the array #this for loop receives the 9 parameters for all the stimulations and adds them to an array for i in range(drumgrating_parasize): #start from 0 to parasize[0] - 1 temp = sock.recv(1024) temp =conv.convStr2Dig(temp) #adding the parameters to the array (temp) at position index paras[i, :] = temp sock.sendto("Para DONE", (Remote_IP, Remote_Port)) try: #recieving all orientation for stimuli 1 for veritcal, 0 for horizontal paratemp = sock.recv(1024) except Exception: sock.close() print("Did not recieve message, connection timeout.") return paratemp = conv.convStr2Dig(paratemp) #setting up the parameters based on what was send in the paras variable drumgrating_Ori = int(paratemp[0]) Motionmode = int(paratemp[1]) drumgrating_Amp_sinu = paratemp[2] drumgrating_addblank = paratemp[3] sock.sendto("Para DONE", (Remote_IP, Remote_Port)) elif drumgrating_controlmod == 'manualVS': return #if Synch is False, this else condition will make the parameters in the same format as if Synch was True else: #making the array in which the parameters will be added to paras = np.empty(shape=[drumgrating_parasize, 9]) #adding the parameters to the array for i in range(drumgrating_parasize): #start from 0 to parasize[0] - 1 #adding the parameters as an array at index i paras[i, :] = [SpatFreqDeg, TempFreq, drumgrating_contrast, drumgrating_MeanLum, drumgrating_dirindex, t_before, t_During, t_after, drumgrating_t_triginit] paratemp = [drumgrating_Ori, Motionmode, drumgrating_Amp_sinu, drumgrating_addblank] #setting up the parameters based on what was send in the paras variable drumgrating_Ori = int(paratemp[0]) Motionmode = int(paratemp[1]) drumgrating_Amp_sinu = paratemp[2] drumgrating_addblank = paratemp[3] if Synch: #get file name $$$$$$$$$$$$$$$$$$$$ while True: try: info = sock.recv(1024) except: pass if info.strip(): #strip spaces print (info) sock.sendto(("nex"), (Remote_IP, Remote_Port)) break if mouse.getPressed()[1]: sock.close() return #$$$$$$$$$$$$$$$$$$$$$$$$$$ #waiting for "STR" while True: try: info = sock.recv(1024) except: pass if info == "STR": sock.sendto(("VS is running"), (Remote_IP, Remote_Port)) break if mouse.getPressed()[1]: sock.close() return #generating the pixel angles relaive to the mouse position based on the orientation of the stimulus if drumgrating_Ori == 1: #generating matrix that will be the place holder for every pixel pixelangle = np.empty(shape=[1, winWidth]) #pixel has to be 2D since the image is 2D temp = np.array(range(winWidthofEachDisp)) temp.reshape(1,winWidthofEachDisp)# the temp must be 2D tempPixelAngle = np.degrees(np.arctan((temp - (winWidthofEachDisp/2.0))*PixelSize*(2.0/DisplayFrameWidth))) + 45 #calculating the pixel angle for first monitor for i in range(ScrnNum): pixelangle[:,i*winWidthofEachDisp: (i + 1)*winWidthofEachDisp ] = tempPixelAngle + 90*i #taking specific ranges within the full winWidth and replacing the values with the corresponding angles else: return for m in range(drumgrating_parasize): tic = clock.getTime() if m == 0: SpatFreqDeg = paras[m, 0] TempFreq = paras[m, 1] drumgrating_contrast = paras[m, 2] drumgrating_MeanLum = paras[m, 3] drumgrating_dirindex = paras[m, 4] t_before = paras[m, 5] t_During = paras[m, 6] t_after = paras[m, 7] drumgrating_t_triginit = paras[m, 8] pixelformeanlum = 2*(np.exp(np.log(drumgrating_MeanLum/drumgrating_AmpFactor)/drumgrating_GammaFactor)/255.0) -1 drumgrating_gray = drumgrating_MeanLum inc = drumgrating_gray*drumgrating_contrast #frames to be calculated per period frames = round(FR/TempFreq) phase = np.array(range(int(frames))) if Motionmode == 1: phase = (phase/float(round(frames)))*(2.0*np.pi) elif Motionmode == 0: phase = drumgrating_Amp_sinu*np.sin((phase/frames)*2*np.pi)*SpatFreqDeg*2*np.pi #generating the pixel values for the stimulus depending on the orientation of the stimulus if drumgrating_Ori == 1: #creating the list that will hold all frames texdata1D = [] #generating the pixel values for vertical stimulus for i in range(int(frames)): texdata1DTmp = np.exp(np.log((drumgrating_gray + inc*np.sin(pixelangle*SpatFreqDeg*2*np.pi + phase[i]))/drumgrating_AmpFactor)/drumgrating_GammaFactor) pixVal = 2*(texdata1DTmp/255) - 1 #converting the pixel values from 0:255 to -1:1 texdata1D.append(pixVal) else: return else: if sum(abs(paras[m, :] - paras[m-1, :])) > 1e-7: #if (not all([v == 0 for v in abs(paras[m, :] - paras[m-1, :])])): SpatFreqDeg = paras[m, 0] TempFreq = paras[m, 1] drumgrating_contrast = paras[m, 2] drumgrating_MeanLum = paras[m, 3] drumgrating_dirindex = paras[m, 4] t_before = paras[m, 5] t_During = paras[m, 6] t_afterVal = paras[m, 7] drumgrating_t_triginit = paras[m, 8] pixelformeanlum = 2*(np.exp(np.log(drumgrating_MeanLum/drumgrating_AmpFactor)/drumgrating_GammaFactor)/255.0) -1 drumgrating_gray = drumgrating_MeanLum inc = drumgrating_gray*drumgrating_contrast #frames to be calculated per period frames = round(FR/TempFreq) phase = np.array(range(int(frames))) if Motionmode == 1: phase = (phase/float(round(frames)))*(2.0*np.pi) elif Motionmode == 0: phase = drumgrating_Amp_sinu*np.sin((phase/frames)*2*np.pi)*SpatFreqDeg*2*np.pi #generating the pixel values for the stimulus depending on the orientation of the stimulus if drumgrating_Ori == 1: #creating the list that will hold all frames texdata1D = [] #generating the pixel values for vertical stimulus for i in range(int(frames)): texdata1DTmp = np.exp(np.log((drumgrating_gray + inc*np.sin(pixelangle*SpatFreqDeg*2*np.pi + phase[i]))/drumgrating_AmpFactor)/drumgrating_GammaFactor) pixVal = 2*(texdata1DTmp/255) - 1 #converting the pixel values from 0:255 to -1:1 texdata1D.append(pixVal) else: return #creating the looping variable for the simulation depending on the value of drumgrating_addblank if drumgrating_addblank == 0 or drumgrating_addblank == 1: #this variable controls the looping and frame that is to be displayed frmNum = 0 #frame number within one cycle elif drumgrating_addblank == 2 and m == 0: #this variable controls the looping and frame that is to be displayed frmNum = 0 #frame number within one cycle #setting up the grating DrawTexture = visual.GratingStim( win=win, size = [winWidth, winHeight], units = 'pix', tex=texdata1D[0] ) if Synch: #waiting for "TRLstart", if TRLstart is sent this loop will send "TRLstart m" then break sock.settimeout(0.5) comm = [""] while True: try: comm = sock.recvfrom(1024) except Exception: pass if comm[0] == "TRLstart": sock.sendto(("TRLstart " + str(m +1)), (Remote_IP, Remote_Port)) break elif comm[0] == "ESC1": #if 'ESC1' is in the buffer, return to front sock.close() return if mouse.getPressed()[1]: sock.close() print("Exit at ESC1") return if drumgrating_addblank == 1.0: win.color = pixelformeanlum elif drumgrating_addblank == 0.0: DrawTexture.draw() elif drumgrating_addblank == 2.0: DrawTexture.tex = texdata1D[frmNum] DrawTexture.draw() frmNum = frmNum + 1 if frmNum >= len(texdata1D): frmNum = 0 square1.draw() square2.draw() win.flip() #time before the stimulation toc = clock.getTime() - tic while toc < (t_before/1000.0): toc = clock.getTime() - tic if drumgrating_addblank == 2: #assigning the texture using the corrusponding frame DrawTexture.tex = texdata1D[frmNum] #this if statement is for existing the stimulation if mouse.getPressed()[1]: if Synch: sock.close() return frmNum = frmNum + 1 if frmNum >= len(texdata1D): frmNum = 0 DrawTexture.draw() square1.draw() square2.draw() win.flip() #t_triger initial timing for triggerin the camera for i in range(int(FR*drumgrating_t_triginit/1000.0)): if i < 3: square1.fillColor = [1,1,1] square2.fillColor = [-1,-1,-1] else: square1.fillColor = [-1,-1,-1] square2.fillColor = [-1,-1,-1] if drumgrating_addblank == 1.0: win.color = pixelformeanlum elif drumgrating_addblank == 0.0: DrawTexture.draw() elif drumgrating_addblank == 2.0: #assigning the texture using the corrusponding frame DrawTexture.tex = texdata1D[frmNum] frmNum = frmNum + 1 if frmNum >= len(texdata1D): frmNum = 0 DrawTexture.draw() if mouse.getPressed()[1]: if Synch: sock.close() return square1.draw() square2.draw() win.flip() #making the top square white square1.fillColor = [-1,-1,-1] square2.fillColor = [1,1,1] #drawing the frames on the window for frm in range(int(FR*t_During/1000.0)): #assigning the texture using the corrusponding frame DrawTexture.tex = texdata1D[frmNum] #this if statement is for existing the stimulation if mouse.getPressed()[1]: if Synch: sock.close() return frmNum = frmNum + 1 if frmNum >= len(texdata1D): frmNum = 0 DrawTexture.draw() square1.draw() square2.draw() win.flip() if Synch: sock.sendto(("TRLdone " + str(m +1)), (Remote_IP, Remote_Port)) #changing the characteristics of the two squares at the bottom left corner square1.fillColor = [-1,-1,-1] square2.fillColor = [-1,-1,-1] #time after the stimulation for toc in range(int(t_after*FR/1000.0)): if drumgrating_addblank == 1.0: win.color = pixelformeanlum elif drumgrating_addblank == 0.0: DrawTexture.draw() elif drumgrating_addblank == 2: #assigning the texture using the corrusponding frame DrawTexture.tex = texdata1D[frmNum] frmNum = frmNum + 1 if frmNum >= len(texdata1D): frmNum = 0 DrawTexture.draw() square1.draw() square2.draw() win.flip() if Synch: #checking for stop button while True: try: comm = sock.recvfrom(1024) except: pass if comm[0] == "ESC1": sock.close() return elif comm[0] == "ESC0": break elif mouse.getPressed()[1]: sock.close() print("Exit at ESC2") return
def calibration(win): ''' input: win (define a window) output: vis stim with varying lum val changing based on log scale This function will generate static grating will changing luminance (using log scale). This visual stim will be used to calibrate the eye tracking system. NOTE: the relationship beteen pupil size and luminance is logarithmic; therefore the steps by which the liminance is increase follow a log scale; ''' import numpy as np from psychopy import event, visual, core from init_para import (MovSinGrat_Amp_sinu, MovSinGrat_GammaFactor, MovSinGrat_AmpFactor, MovSinGrat_contrast, MovSinGrat_MeanLum, win, winWidth, winHeight, ScrnNum, PixelSize, winWidthofEachDisp, DisplayFrameWidth, FR, square1, square2, fontSize, fontClr, win, Local_IP, Local_Port, Remote_IP, Remote_Port) #define parameters WholeWinwidth = winWidth WinWidthofEachdisp = winWidth / ScrnNum #set the type of pattern for the calibration: calib_pattern = 0 if calib_pattern: #1 = gratting, 0 = uniform maximum = (MovSinGrat_AmpFactor * 250**MovSinGrat_GammaFactor ) / 2 #the max elgible val for MeanLum in cd/m^2 else: maximum = (MovSinGrat_AmpFactor * 250**MovSinGrat_GammaFactor ) #the max elgible val for MeanLum in cd/m^2 #minimum = (MovSinGrat_AmpFactor*1**MovSinGrat_GammaFactor)/2 #the min elgible val for MeanLum incd/m^2 minimum = 15 log_max = np.log(maximum) log_min = np.log(minimum) num_step = 5 #but total steps plus 2 0 log_step = (log_max - log_min) / num_step Contrast = 1 temp = np.array(range(0, (num_step + 1))) log_lum_val = log_min + log_step * (temp) lum_val_list = np.exp(log_lum_val) lum_val_list = np.append([0], lum_val_list) lum_val = lum_val_list[0] step_count = 0 #counter to loop around lum values inc = lum_val * Contrast #increase the step by this variable SpatFreqDeg = 0.1 #MeanLum = (maximum)/2 phase = 0 #in radius #generating matrix that will be the place holder for every pixel pixelangle = np.empty(shape=[1, winWidth ]) #pixel has to be 2D since the image is 2D temp = np.array(range(winWidthofEachDisp)) temp.reshape(1, winWidthofEachDisp) # the temp must be 2D tempPixelAngle = np.degrees( np.arctan((temp - (winWidthofEachDisp / 2.0)) * PixelSize * (2.0 / DisplayFrameWidth)) ) + 45 #calculating the pixel angle for first monitor for i in range(ScrnNum): pixelangle[:, i * winWidthofEachDisp:( i + 1 ) * winWidthofEachDisp] = tempPixelAngle + 90 * i #taking specific ranges within the full winWidth and replacing the values with the corresponding angles #generating the pixel values for vertical stimulus texdata1DTmp = np.exp( np.log((lum_val + inc * np.sin(pixelangle * SpatFreqDeg * 2 * np.pi + phase)) / MovSinGrat_AmpFactor) / MovSinGrat_GammaFactor) pixVal = 2 * (texdata1DTmp / 255) - 1 #converting the pixel values from 0:255 to -1:1 if not calib_pattern: #for uniform mask, set pixval to single lum_val uniform_pix = np.exp( np.log(lum_val / MovSinGrat_AmpFactor) / MovSinGrat_GammaFactor) pixVal[:] = 2 * (uniform_pix / 255) - 1 #setting up the grating DrawTexture = visual.GratingStim(win=win, size=[winWidth, winHeight], units='pix', tex=pixVal) #display current lumninance value lum_text = visual.TextBox(window=win, text=(str('%.1f' % (lum_val))), font_size=fontSize + 7, font_color=[1, 1, 1], pos=(WholeWinwidth / 2 * (-1) + 50, winHeight / 2 - 25), size=(300, 37), units='pix', grid_horz_justification='center', grid_vert_justification='center') #draw grating and lum val DrawTexture.draw() lum_text.draw() #flip window and display gratting and lum val win.flip() mouse = event.Mouse(visible=True, win=win) #display grating; and allow user to modify luminance of the grating according to right and left clic while True: core.wait(0.1) #get keys currMouse = mouse.getPressed() #clicking the middle button causes program to close if currMouse[1]: break #left clic: increase lum if currMouse[0]: #increase counter (starts at 0) step_count += 1 #increase by increment value LOG lum_val = lum_val_list[step_count % (len(lum_val_list))] inc = lum_val * Contrast #regenerating the pixel values texdata1DTmp = np.exp( np.log((lum_val + inc * np.sin(pixelangle * SpatFreqDeg * 2 * np.pi + phase)) / MovSinGrat_AmpFactor) / MovSinGrat_GammaFactor) pixVal = 2 * ( texdata1DTmp / 255) - 1 #converting the pixel values from 0:255 to -1:1 if not calib_pattern: #for uniform mask, set pixval to single lum_val uniform_pix = np.exp( np.log(lum_val / MovSinGrat_AmpFactor) / MovSinGrat_GammaFactor) pixVal[:] = 2 * (uniform_pix / 255) - 1 #redraw texture and new lum val #setting up the grating DrawTexture = visual.GratingStim(win=win, size=[winWidth, winHeight], units='pix', tex=pixVal) #display current lumninance value lum_text = visual.TextBox(window=win, text=(str('%.1f' % (lum_val))), font_size=fontSize + 7, font_color=[1, 1, 1], pos=(WholeWinwidth / 2 * (-1) + 50, winHeight / 2 - 25), size=(300, 37), units='pix', grid_horz_justification='center', grid_vert_justification='center') #draw grating and lum val DrawTexture.draw() lum_text.draw() #flip window and display gratting and lum val win.flip() while any(currMouse): currMouse = mouse.getPressed() if currMouse[2]: #right clic: decrease lum #increase counter (starts at 0) step_count -= 1 #increase by increment value lum_val = lum_val_list[step_count % (len(lum_val_list))] inc = lum_val * Contrast #regenerating the pixel values from luminance val texdata1DTmp = np.exp( np.log((lum_val + inc * np.sin(pixelangle * SpatFreqDeg * 2 * np.pi + phase)) / MovSinGrat_AmpFactor) / MovSinGrat_GammaFactor) pixVal = 2 * ( texdata1DTmp / 255) - 1 #converting the pixel values from 0:255 to -1:1 if not calib_pattern: #for uniform mask, set all of pixval to lum_val uniform_pix = np.exp( np.log(lum_val / MovSinGrat_AmpFactor) / MovSinGrat_GammaFactor) pixVal[:] = 2 * (uniform_pix / 255) - 1 #redraw texture and new lum val #setting up the grating DrawTexture = visual.GratingStim(win=win, size=[winWidth, winHeight], units='pix', tex=pixVal) #display current lumninance value lum_text = visual.TextBox(window=win, text=(str('%.1f' % (lum_val))), font_size=fontSize + 7, font_color=[1, 1, 1], pos=(WholeWinwidth / 2 * (-1) + 50, winHeight / 2 - 25), size=(300, 37), units='pix', grid_horz_justification='center', grid_vert_justification='center') #draw grating and lum val DrawTexture.draw() lum_text.draw() #flip window and display gratting and lum val win.flip() while any(currMouse): currMouse = mouse.getPressed() while any(currMouse): currMouse = mouse.getPressed() return
def movSinGrat(MovSinGrat_SpatFreqVal, MovSinGrat_tempFreqVal, MovSinGrat_t_before, MovSinGrat_t_During, MovSinGrat_t_after, Synch, MovSinGrat_Motionmode, MovSinGrat_features, MovSinGrat_ledstate): ''' INPUT: paramterS that are potentially changed by user in front.py by clicking buttons on the UI OUTPUT: vs stimuli for tuning, depending on the feature selected; default is 'ori' which can be changed in init_para.py; Note >> TUNING FEATURE VALUES are defined as follows: # ori = 0, spat_freq = 1, temp_freq = 2, contrast = 3, location = 4 ''' from psychopy import visual, event, clock, gui from win32api import GetSystemMetrics from datetime import datetime from init_para import ( MovSinGrat_addblank, MovSinGrat_Amp_sinu, MovSinGrat_controlmod, MovSinGrat_dirindex, MovSinGrat_ori, MovSinGrat_t_triginit, MovSinGrat_GammaFactor, MovSinGrat_AmpFactor, MovSinGrat_contrast, MovSinGrat_MeanLum, win, winWidth, winHeight, ScrnNum, PixelSize, winWidthofEachDisp, DisplayFrameWidth, FR, square1, square2, mask_L, mask_R, fontSize, fontClr, win, Local_IP, Local_Port, Remote_IP, Remote_Port, ani_distance, MovSinGrat_Rep, MovSinGrat_randomseq, MovSinGrat_features_dict, MovSinGrat_angles_list, MovSinGrat_temp_lin_list, MovSinGrat_temp_osc_list, MovSinGrat_location_list, MovSinGrat_contrast_list) import socket import numpy as np import conv #To display vs on a single screen set one_screen = True: one_screen = True #creating mouse functionality mouse = event.Mouse(visible=True, win=win) if Synch: #creating the socket in which communications will take place sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) #binding the local IP address and local port sock.bind((Local_IP, Local_Port)) #creating textbox showing that this VS computer is waiting for UDP signal standBy = visual.TextBox( window=win, text=("Waiting for starting the control computer."), font_size=fontSize, font_color=fontClr, pos=(-2690, 475), size=(300, 37), units='pix', grid_horz_justification='center', grid_vert_justification='center') standBy.draw() square1.draw( ) #have to draw trigger squ; otherwise transient white will happen square2.draw() win.flip() try: #wait for the command 'gammacorrection' info = sock.recv(1024) except Exception: sock.close() print("Did not recieve info, connection timeout.") return #sending 'gammafloatampfloat' to the second PC sock.sendto(("gamma" + str(drumgrating_GammaFactor) + "amp" + str(drumgrating_AmpFactor)), (Remote_IP, Remote_Port)) #creating textbox showing that this VS computer is waiting for UDP signal standBy = visual.TextBox(window=win, text=("Control Computer is Ready."), font_size=fontSize, font_color=fontClr, pos=(-2690, 475), size=(300, 37), units='pix', grid_horz_justification='center', grid_vert_justification='center') standBy.draw() try: #waiting for the signal autoVs drumgrating_controlmod = sock.recv(1024) except Exception: sock.close() print( "Did not recieve drumgrating_controlmod, connection timeout.") return #sending 'Wait for parameters' to the second PC sock.sendto("Wait for parameters", (Remote_IP, Remote_Port)) if MovSinGrat_controlmod == 'autoVS': try: drumgrating_parasize = sock.recv(1024) except Exception: sock.close() print("Did not recieve parasize, connection timeout.") return #sending a completion transcript sock.sendto("read parasize", (Remote_IP, Remote_Port)) #converting the string recieved into int drumgrating_parasize = conv.deleteParasize(drumgrating_parasize) #making the array in which the parameters will be added to paras = np.empty(shape=[drumgrating_parasize, 9]) #adding the parameters to the array #this for loop receives the 9 parameters for all the stimulations and adds them to an array for i in range( drumgrating_parasize): #start from 0 to parasize[0] - 1 temp = sock.recv(1024) temp = conv.convStr2Dig(temp) #adding the parameters to the array (temp) at position index #paras[i, :] = temp sock.sendto("Para DONE", (Remote_IP, Remote_Port)) try: #recieving all orientation for stimuli 1 for veritcal, 0 for horizontal paratemp = sock.recv(1024) except Exception: sock.close() print("Did not recieve message, connection timeout.") return paratemp = conv.convStr2Dig(paratemp) #setting up the parameters based on what was send in the paras variable drumgrating_Ori = int(paratemp[0]) Motionmode = int(paratemp[1]) drumgrating_Amp_sinu = paratemp[2] drumgrating_addblank = paratemp[3] sock.sendto("Para DONE", (Remote_IP, Remote_Port)) #creating generalized sequence of randomely shuffled stimuli for tuning, given a particular feature #This firt if loop will create two varialbes: #tuning_stim_val and tuning_stim_ind which contains all unique stimulus and corresponding index, respectively, given the tuning feature selected. if MovSinGrat_features == 0: #ori tuning_stim_val = map( float, MovSinGrat_angles_list ) #map applies the float() function to all elements of the list, therefore converting strings to float tuning_stim_ind = range(len(tuning_stim_val)) elif MovSinGrat_features == 1: #spat_freq tuning_stim_val = map(float, MovSinGrat_spat_list) tuning_stim_ind = range(len(tuning_stim_val)) elif MovSinGrat_features == 2: #temp_freq #assign temp freq depending on Motionmode (lin vs osc motion) if MovSinGrat_Motionmode == 0: tuning_stim_val = map( float, MovSinGrat_temp_lin_list ) #SHOULD THIS BE DEPENDENT ON MOTIONMODE??? tuning_stim_ind = range(len(tuning_stim_val)) else: tuning_stim_val = map( float, MovSinGrat_temp_osc_list ) #SHOULD THIS BE DEPENDENT ON MOTIONMODE??? tuning_stim_ind = range(len(tuning_stim_val)) elif MovSinGrat_features == 3: #contrast tuning_stim_val = MovSinGrat_contrast_list #HAS NOT BEEN CREATED IN INIT_PARA YET; tuning_stim_ind = range(len(tuning_stim_val)) elif MovSinGrat_features == 4: #location tuning_stim_val = map(float, MovSinGrat_location_list) tuning_stim_ind = range(len(tuning_stim_val)) else: print 'ERROR: MovSinGrat_features outside range. Tuning Feature Value must an integer be between 0 and 4.' #calculating total number of stimuli that will be presented (based on number of repetitions for each stimulus*ledstate combo) tot_num_stim = MovSinGrat_Rep * MovSinGrat_ledstate * len( tuning_stim_ind) #defining the variable and array shape in which the parameters will be added to; each column will represent on parameter (spat_freq, temp_freq, stimId etc.) for each presented stimulus (row) paras = np.empty(shape=[tot_num_stim, 12]) #adding the parameters to the array # Generating sequence of order of presenting stimID that will ONLY change the TUNING FEATURE PARAMETER of the stimulus: for repind in xrange(MovSinGrat_Rep): stimId = np.empty(len(tuning_stim_ind) * MovSinGrat_ledstate) stimId = map(int, stimId) if MovSinGrat_randomseq: for iled in xrange( 0, MovSinGrat_ledstate ): #for each ledstate, one of each angle will be assoign in random order np.random.shuffle(tuning_stim_ind) for n in xrange( iled, len(stimId), MovSinGrat_ledstate ): #assign tuning_stim_ind elements to stimId by hops of size ledstate (if ledstate = 1), stimId = tuning_stim_ind; stimId[n] = tuning_stim_ind[n / MovSinGrat_ledstate] # else: for iled in xrange(0, MovSinGrat_ledstate): for n in xrange(iled, len(stimId), MovSinGrat_ledstate): stimId[n] = tuning_stim_ind[n / MovSinGrat_ledstate] #adding the parameters as an array at index i for localstimid in xrange(0, (len(stimId))): if MovSinGrat_features == 0: #0 = ori paras[repind * (len(stimId)) + localstimid, :] = [ MovSinGrat_SpatFreqVal, MovSinGrat_tempFreqVal, MovSinGrat_contrast, MovSinGrat_MeanLum, MovSinGrat_dirindex, MovSinGrat_t_before, MovSinGrat_t_During, MovSinGrat_t_after, MovSinGrat_t_triginit, tuning_stim_val[stimId[localstimid]], MovSinGrat_ledstate, 0 ] # ADD LOCATION elif MovSinGrat_features == 1: #1 = spat paras[repind * (len(stimId)) + localstimid, :] = [ tuning_stim_val[stimId[localstimid]], MovSinGrat_tempFreqVal, MovSinGrat_contrast, MovSinGrat_MeanLum, MovSinGrat_dirindex, MovSinGrat_t_before, MovSinGrat_t_During, MovSinGrat_t_after, MovSinGrat_t_triginit, MovSinGrat_ori, MovSinGrat_ledstate, 0 ] #ADD LOCATION elif MovSinGrat_features == 2: # and movSinGrat_motionMode == 0: #2 = TempFreq paras[repind * (len(stimId)) + localstimid, :] = [ MovSinGrat_SpatFreqVal, tuning_stim_val[stimId[localstimid]], MovSinGrat_contrast, MovSinGrat_MeanLum, MovSinGrat_dirindex, MovSinGrat_t_before, MovSinGrat_t_During, MovSinGrat_t_after, MovSinGrat_t_triginit, MovSinGrat_ori, MovSinGrat_ledstate, 0 ] #ADD LOCATION elif MovSinGrat_features == 3: #3 = contrast paras[repind * (len(stimId)) + localstimid, :] = [ MovSinGrat_SpatFreqVal, MovSinGrat_tempFreqVal, tuning_stim_val[stimId[localstimid]], MovSinGrat_MeanLum, MovSinGrat_dirindex, MovSinGrat_t_before, MovSinGrat_t_During, MovSinGrat_t_after, MovSinGrat_t_triginit, MovSinGrat_ori, MovSinGrat_ledstate, 0 ] #ADD LOCATION #elif MovSinGrat_features == 4: #4 = location # paras[repind*(len(stimId))+localstimid, :] = [MovSinGrat_SpatFreqVal, MovSinGrat_tempFreqVal, MovSinGrat_contrast, MovSinGrat_MeanLum, MovSinGrat_dirindex, # MovSinGrat_t_before, MovSinGrat_t_During, MovSinGrat_t_after, MovSinGrat_t_triginit, MovSinGrat_ori, MovSinGrat_ledstate, 0] #ADD LOCATION paratemp = [ drumgrating_Ori, Motionmode, drumgrating_Amp_sinu, drumgrating_addblank ] #setting up the parameters based on what was send in the paras variable drumgrating_Ori = int(paratemp[0]) Motionmode = int(paratemp[1]) drumgrating_Amp_sinu = paratemp[2] drumgrating_addblank = paratemp[3] elif MovSinGrat_controlmod == 'manualVS': return #if Synch is False, this else condition will make the parameters in the same format as if Synch was True else: #Naming the experiment to create fileName (at the end of this function) instruction_text = visual.TextStim( win, text=u'Name experiment and press enter to start.', pos=(0, 0.5)) answer_text = visual.TextStim(win) #show instructions instruction_text.draw() square1.draw( ) #have to draw trigger squ; otherwise transient white will happen$$$$$$$$$$$$$$$ square2.draw() win.flip() #get users input for experiment name now = True answer_text.text = '' while now: key = event.waitKeys()[0] # Add a new number if key in '1234567890abcdfeghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_-': answer_text.text += key # Delete last character, if there are any chars at all elif key == 'backspace' and len(answer_text.text) > 0: answer_text.text = answer_text.text[:-1] # Stop collecting response and return it elif key == 'return': expName = answer_text.text print('expName IN here: ', expName) now = False # Show current answer state instruction_text.draw() answer_text.draw() square1.draw( ) #have to draw trigger squ; otherwise transient white will happen$$$$$$$$$$$$$ square2.draw() win.flip() #setting name of file which will be used to save order of vs stim displayed; NAME = MVS (movSinGrat) + type of tuning feature manipulated in experiment + datetime feature = MovSinGrat_features_dict.keys() date = datetime.today().strftime( '%Y%m%d_%H%M%S') #extract today's date fileName = expName + '_vs_' + feature[ MovSinGrat_features] + '_' + date #exp name defined above either by user (if not synch) or by eye tracking software (if user) #creating generalized sequence of randomely shuffled stimuli for tuning, given a particular feature #This firt if loop will create two varialbes: #tuning_stim_val and tuning_stim_ind which contains all unique stimulus and corresponding index, respectively, given the tuning feature selected. if MovSinGrat_features == 0: #ori tuning_stim_val = map( float, MovSinGrat_angles_list ) #map applies the float() function to all elements of the list, therefore converting strings to float tuning_stim_ind = range(len(tuning_stim_val)) elif MovSinGrat_features == 1: #spat_freq tuning_stim_val = map(float, MovSinGrat_spat_list) tuning_stim_ind = range(len(tuning_stim_val)) elif MovSinGrat_features == 2: #temp_freq #assign temp freq depending on Motionmode (lin vs osc motion) if MovSinGrat_Motionmode == 0: tuning_stim_val = map(float, MovSinGrat_temp_lin_list) tuning_stim_ind = range(len(tuning_stim_val)) else: tuning_stim_val = map(float, MovSinGrat_temp_osc_list) tuning_stim_ind = range(len(tuning_stim_val)) elif MovSinGrat_features == 3: #contrast tuning_stim_val = MovSinGrat_contrast_list tuning_stim_ind = range(len(tuning_stim_val)) elif MovSinGrat_features == 4: #location tuning_stim_val = map(float, MovSinGrat_location_list) tuning_stim_ind = range(len(tuning_stim_val)) else: print 'ERROR: MovSinGrat_features outside range. Tuning Feature Value must an integer be between 0 and 4.' #calculating total number of stimuli that will be presented (based on number of repetitions for each stimulus*ledstate combo) tot_num_stim = MovSinGrat_Rep * MovSinGrat_ledstate * len( tuning_stim_ind) #defining the variable and array shape in which the parameters will be added to; each column will represent on parameter (spat_freq, temp_freq, stimId etc.) for each presented stimulus (row) paras = np.empty(shape=[tot_num_stim, 12]) #adding the parameters to the array # Generating sequence of order of presenting stimID that will ONLY change the TUNING FEATURE PARAMETER of the stimulus: for repind in xrange(MovSinGrat_Rep): stimId = np.empty(len(tuning_stim_ind) * MovSinGrat_ledstate) stimId = map(int, stimId) if MovSinGrat_randomseq: for iled in xrange( 0, MovSinGrat_ledstate ): #for each ledstate, one of each angle will be assoign in random order np.random.shuffle(tuning_stim_ind) for n in xrange( iled, len(stimId), MovSinGrat_ledstate ): #assign tuning_stim_ind elements to stimId by hops of size ledstate (if ledstate = 1), stimId = tuning_stim_ind; stimId[n] = tuning_stim_ind[n / MovSinGrat_ledstate] else: for iled in xrange(0, MovSinGrat_ledstate): for n in xrange(iled, len(stimId), MovSinGrat_ledstate): stimId[n] = tuning_stim_ind[n / MovSinGrat_ledstate] #adding the parameters as an array at index i for localstimid in xrange(0, (len(stimId))): if MovSinGrat_features == 0: #0 = ori paras[repind * (len(stimId)) + localstimid, :] = [ MovSinGrat_SpatFreqVal, MovSinGrat_tempFreqVal, MovSinGrat_contrast, MovSinGrat_MeanLum, MovSinGrat_dirindex, MovSinGrat_t_before, MovSinGrat_t_During, MovSinGrat_t_after, MovSinGrat_t_triginit, tuning_stim_val[stimId[localstimid]], MovSinGrat_ledstate, 0 ] # ADD LOCATION elif MovSinGrat_features == 1: #1 = spat paras[repind * (len(stimId)) + localstimid, :] = [ tuning_stim_val[stimId[localstimid]], MovSinGrat_tempFreqVal, MovSinGrat_contrast, MovSinGrat_MeanLum, MovSinGrat_dirindex, MovSinGrat_t_before, MovSinGrat_t_During, MovSinGrat_t_after, MovSinGrat_t_triginit, MovSinGrat_ori, MovSinGrat_ledstate, 0 ] #ADD LOCATION elif MovSinGrat_features == 2: # and movSinGrat_motionMode == 0: #2 = TempFreq paras[repind * (len(stimId)) + localstimid, :] = [ MovSinGrat_SpatFreqVal, tuning_stim_val[stimId[localstimid]], MovSinGrat_contrast, MovSinGrat_MeanLum, MovSinGrat_dirindex, MovSinGrat_t_before, MovSinGrat_t_During, MovSinGrat_t_after, MovSinGrat_t_triginit, MovSinGrat_ori, MovSinGrat_ledstate, 0 ] #ADD LOCATION elif MovSinGrat_features == 4: #4 = contrast paras[repind * (len(stimId)) + localstimid, :] = [ MovSinGrat_SpatFreqVal, MovSinGrat_tempFreqVal, tuning_stim_val[stimId[localstimid]], MovSinGrat_MeanLum, MovSinGrat_dirindex, MovSinGrat_t_before, MovSinGrat_t_During, MovSinGrat_t_after, MovSinGrat_t_triginit, MovSinGrat_ori, MovSinGrat_ledstate, 0 ] #ADD LOCATION #elif MovSinGrat_features == 5: #5 = location # paras[repind*(len(stimId))+localstimid, :] = [MovSinGrat_SpatFreqVal, MovSinGrat_tempFreqVal, MovSinGrat_contrast, MovSinGrat_MeanLum, MovSinGrat_dirindex, # MovSinGrat_t_before, MovSinGrat_t_During, MovSinGrat_t_after, MovSinGrat_t_triginit, MovSinGrat_ori, MovSinGrat_ledstate, 0] #ADD LOCATION #paratemp = [drumgrating_Ori, Motionmode, drumgrating_Amp_sinu, drumgrating_addblank] #setting up the parameters based on what was send in the paras variable #drumgrating_Ori = int(paratemp[0]) #Motionmode = int(paratemp[1]) #drumgrating_Amp_sinu = paratemp[2] #drumgrating_addblank = paratemp[3] if Synch: #waiting for "STR" while True: try: info = sock.recv(1024) except: pass if info == "STR": sock.sendto(("VS is running"), (Remote_IP, Remote_Port)) break if mouse.getPressed()[1]: sock.close() return #generating the pixel angles relaive to the mouse position based on the orientation of the stimulus #generating matrix that will be the place holder for every pixel pixelangle = np.empty(shape=[1, winWidth ]) #pixel has to be 2D since the image is 2D temp = np.array(range(winWidthofEachDisp)) temp.reshape(1, winWidthofEachDisp) # the temp must be 2D #tempPixelAngle = np.degrees(np.arctan((temp - (winWidthofEachDisp/2.0))*PixelSize*(2.0/DisplayFrameWidth))) + 45 #calculating the pixel angle for first monitor spatangperpix = np.degrees(np.arctan(PixelSize / ani_distance)) tempPixelAngle = spatangperpix * temp for i in range(ScrnNum): pixelangle[:, i * winWidthofEachDisp:( i + 1 ) * winWidthofEachDisp] = tempPixelAngle + 90 * i #taking specific ranges within the full winWidth and replacing the values with the corresponding angles #Genereating the VS based on the parameters in paras for m in xrange(tot_num_stim): paras[m, 11] = 1 #marks which stim have been presented to the animal tic = clock.getTime() if m == 0: SpatFreqDeg = paras[m, 0] TempFreq = paras[m, 1] contrast = paras[m, 2] MeanLum = paras[m, 3] dirindex = paras[m, 4] t_before = paras[m, 5] t_During = paras[m, 6] t_after = paras[m, 7] t_triginit = paras[m, 8] orientation = paras[m, 9] ledstate = paras[m, 10] pixelformeanlum = 2 * (np.exp( np.log(MovSinGrat_MeanLum / MovSinGrat_AmpFactor) / MovSinGrat_GammaFactor) / 255.0) - 1 MovSinGrat_gray = MovSinGrat_MeanLum inc = MovSinGrat_gray * MovSinGrat_contrast #frames to be calculated per period frames = round(FR / TempFreq) phase = np.array(range(int(frames))) if MovSinGrat_Motionmode == 1: phase = (phase / float(round(frames))) * (2.0 * np.pi) elif MovSinGrat_Motionmode == 0: phase = MovSinGrat_Amp_sinu * np.sin( (phase / frames) * 2 * np.pi) * SpatFreqDeg * 2 * np.pi #generating the pixel values for the stimulus #creating the list that will hold all frames texdata1D = [] #generating the pixel values for vertical stimulus for i in range(int(frames)): texdata1DTmp = np.exp( np.log((MovSinGrat_gray + inc * np.sin(pixelangle * SpatFreqDeg * 2 * np.pi + phase[i])) / MovSinGrat_AmpFactor) / MovSinGrat_GammaFactor) pixVal = 2 * ( texdata1DTmp / 255) - 1 #converting the pixel values from 0:255 to -1:1 texdata1D.append(pixVal) else: if sum(abs(paras[m, :] - paras[m - 1, :])) > 1e-7: #if (not all([v == 0 for v in abs(paras[m, :] - paras[m-1, :])])): SpatFreqDeg = paras[m, 0] TempFreq = paras[m, 1] MovSinGrat_contrast = paras[m, 2] MovSinGrat_MeanLum = paras[m, 3] MovSinGrat_dirindex = paras[m, 4] t_before = paras[m, 5] t_During = paras[m, 6] t_afterVal = paras[m, 7] MovSinGrat_t_triginit = paras[m, 8] orientation = paras[m, 9] ledstate = paras[m, 10] pixelformeanlum = 2 * (np.exp( np.log(MovSinGrat_MeanLum / MovSinGrat_AmpFactor) / MovSinGrat_GammaFactor) / 255.0) - 1 MovSinGrat_gray = MovSinGrat_MeanLum inc = MovSinGrat_gray * MovSinGrat_contrast #frames to be calculated per period frames = round(FR / TempFreq) phase = np.array(range(int(frames))) if MovSinGrat_Motionmode == 1: phase = (phase / float(round(frames))) * (2.0 * np.pi) elif MovSinGrat_Motionmode == 0: phase = MovSinGrat_Amp_sinu * np.sin( (phase / frames) * 2 * np.pi) * SpatFreqDeg * 2 * np.pi #generating the pixel values for the stimulus #creating the list that will hold all frames texdata1D = [] #generating the pixel values for vertical stimulus for i in range(int(frames)): texdata1DTmp = np.exp( np.log((MovSinGrat_gray + inc * np.sin(pixelangle * SpatFreqDeg * 2 * np.pi + phase[i])) / MovSinGrat_AmpFactor) / MovSinGrat_GammaFactor) pixVal = 2 * ( texdata1DTmp / 255) - 1 #converting the pixel values from 0:255 to -1:1 texdata1D.append(pixVal) #creating the looping variable for the simulation depending on the value of MovSinGrat_addblank if MovSinGrat_addblank == 0 or MovSinGrat_addblank == 1: #this variable controls the looping and frame that is to be displayed frmNum = 0 #frame number within one cycle elif MovSinGrat_addblank == 2 and m == 0: #this variable controls the looping and frame that is to be displayed frmNum = 0 #frame number within one cycle #setting up the grating DrawTexture = visual.GratingStim(win=win, size=[2 * winWidth, 2 * winWidth], units='pix', tex=texdata1D[0], ori=orientation) if Synch: #waiting for "TRLstart", if TRLstart is sent this loop will send "TRLstart m" then break sock.settimeout(0.5) comm = [""] while True: try: comm = sock.recvfrom(1024) except Exception: pass if comm[0] == "TRLstart": sock.sendto(("TRLstart " + str(m + 1)), (Remote_IP, Remote_Port)) break elif comm[ 0] == "ESC1": #if 'ESC1' is in the buffer, return to front sock.close() return if mouse.getPressed()[1]: sock.close() print("Exit at ESC1") return if MovSinGrat_addblank == 1.0: win.color = pixelformeanlum elif MovSinGrat_addblank == 0.0: DrawTexture.draw() elif MovSinGrat_addblank == 2.0: DrawTexture.tex = texdata1D[frmNum] DrawTexture.draw() frmNum = frmNum + 1 if frmNum >= len(texdata1D): frmNum = 0 #mask R and L screen to display stim on front screen only if one_screen: mask_L.draw() mask_R.draw() square1.draw() square2.draw() win.flip() #time before the stimulation toc = clock.getTime() - tic while toc < (t_before / 1000.0): toc = clock.getTime() - tic if MovSinGrat_addblank == 2: #assigning the texture using the corrusponding frame DrawTexture.tex = texdata1D[frmNum] #this if statement is for existing the stimulation if mouse.getPressed()[1]: if Synch: sock.close() return frmNum = frmNum + 1 if frmNum >= len(texdata1D): frmNum = 0 DrawTexture.draw() #mask R and L screen to display stim on front screen only if one_screen: mask_L.draw() mask_R.draw() square1.draw() square2.draw() win.flip() #t_triger initial timing for triggerin the camera for i in range(int(FR * MovSinGrat_t_triginit / 1000.0)): if i < 3: square1.fillColor = [1, 1, 1] square2.fillColor = [-1, -1, -1] else: square1.fillColor = [-1, -1, -1] square2.fillColor = [-1, -1, -1] if MovSinGrat_addblank == 1.0: win.color = pixelformeanlum elif MovSinGrat_addblank == 0.0: DrawTexture.draw() elif MovSinGrat_addblank == 2: #assigning the texture using the corrusponding frame DrawTexture.tex = texdata1D[frmNum] frmNum = frmNum + 1 if frmNum >= len(texdata1D): frmNum = 0 DrawTexture.draw() if mouse.getPressed()[1]: if Synch: sock.close() return #mask R and L screen to display stim on front screen only if one_screen: mask_L.draw() mask_R.draw() square1.draw() square2.draw() win.flip() #making the top square white square1.fillColor = [-1, -1, -1] square2.fillColor = [1, 1, 1] #drawing the frames on the window for frm in range(int(FR * t_During / 1000.0)): #assigning the texture using the corrusponding frame DrawTexture.tex = texdata1D[frmNum] #this if statement is for existing the stimulation if mouse.getPressed()[1]: if Synch: sock.close() return frmNum = frmNum + 1 if frmNum >= len(texdata1D): frmNum = 0 DrawTexture.draw() #mask R and L screen to display stim on front screen only if one_screen: mask_L.draw() mask_R.draw() square1.draw() square2.draw() win.flip() #save vs data in .csv format #create a temp list variable that stores array values that will be appended save_row = paras[m].tolist() #open and append values to new file with open(fileName + '.csv', 'a') as f: for i in range(len(save_row)): f.write(str(save_row[i]) + ',') f.write('\n') if Synch: sock.sendto(("TRLdone " + str(m + 1)), (Remote_IP, Remote_Port)) #changing the characteristics of the two squares at the bottom left corner square1.fillColor = [-1, -1, -1] square2.fillColor = [-1, -1, -1] #time after the stimulation for toc in range(int(t_after * FR / 1000.0)): if MovSinGrat_addblank == 1.0: win.color = pixelformeanlum elif MovSinGrat_addblank == 0.0: DrawTexture.draw() elif MovSinGrat_addblank == 2: #assigning the texture using the corrusponding frame DrawTexture.tex = texdata1D[frmNum] frmNum = frmNum + 1 if frmNum >= len(texdata1D): frmNum = 0 DrawTexture.draw() #mask R and L screen to display stim on front screen only if one_screen: mask_L.draw() mask_R.draw() square1.draw() square2.draw() win.flip() if Synch: #checking for stop button while True: try: comm = sock.recvfrom(1024) except: pass if comm[0] == "ESC1": sock.close() return elif comm[0] == "ESC0": break elif mouse.getPressed()[1]: sock.close() print("Exit at ESC2") return
def rf6x8(win): from psychopy import visual, event, clock, gui from win32api import GetSystemMetrics from datetime import datetime from init_para import (MovSinGrat_addblank, MovSinGrat_Amp_sinu, MovSinGrat_controlmod, MovSinGrat_dirindex, MovSinGrat_ori, MovSinGrat_t_triginit, MovSinGrat_GammaFactor, MovSinGrat_AmpFactor, MovSinGrat_contrast, MovSinGrat_MeanLum, winWidth , winHeight, ScrnNum, PixelSize, winWidthofEachDisp, DisplayFrameWidth, FR, square1, square2, fontSize, fontClr, win, ani_distance) import socket import numpy as np import conv #PARAMETERS #stim time parameters t_before = 1000 t_during = 3000 t_after = 1000 #contrast (stim colour) parameters meanLum = 55 minLum = 0 maxLum = meanLum * 2 gammaFactor = 2.251 ampFactor = 0.0007181 winClr = 2*(np.exp(np.log(meanLum/ampFactor)/gammaFactor)/255.0) -1 #colour of background (in pix val) white = 2*(np.exp(np.log(maxLum/ampFactor)/gammaFactor)/255.0) -1 #convert maxLum into pix value black = -1 #stim order parameters repetition = 2 num_dif_stim = 48*2 #number of location the stimulus (6 x 8 = 48) will be displayed in two colours values with 100% contrast => 48*2 = 96 tot_num_stim = repetition * num_dif_stim #total number of stiumuli that will be displayed in one experiment index = range(num_dif_stim) #number 0-95 representing each location in 6 x 8 screen and black or white colour x_pos = ([0]*6 + [1]*6 +[2]*6 +[3]*6 +[4]*6 +[5]*6 +[6]*6 +[7]*6) * 2 #list of all possible x-coordinate for stim y_pos = range(6)*8*2 #list of all possible y-coordinate for stim colour_list = [white]*48 + [black]*48 #reshape data into numpy array x_pos = np.asarray(x_pos) y_pos = np.asarray(y_pos) colour_list = np.asarray(colour_list) #creating a matrix to store all stim ID (index), position and colour information loc_order = np.ones((96,3), dtype=int) colour_order = np.ones((96,1), dtype=float) loc_order[:,0] = index loc_order[:,1] = x_pos loc_order[:,2] = y_pos colour_order[:,0] = colour_list stim_order = np.concatenate((loc_order, colour_order),axis=1) #create ramdom order for stimuli presentation np.random.shuffle(index) #this function automatically shuffles the input (no need to assign a new var) #stim shape parameters tot_stim = 96 stim_vertices = np.array(([-1./3, 1],[-1./4, 1], [-1./4, 2./3], [-1.0/3, 2./3])) stim_vertices.reshape(4, 2) #reshape to fit psychopy texture requirements #creating visual stimulation display functionality #creating mouse functionality mouse = event.Mouse( visible = True, win = win ) #Naming the experiment to create fileName (at the end of this function) instruction_text = visual.TextStim(win, text = u'Name experiment and press enter to start.', pos=(0, 0.5)) answer_text = visual.TextStim(win) #show instructions win.color = winClr instruction_text.draw() square1.draw() #have to draw trigger squ; otherwise transient white will happen$$$$$$$$$$$$$$$ square2.draw() win.flip() #get users input for experiment name now = True answer_text.text = '' while now: key = event.waitKeys()[0] # Add a new number if key in '1234567890abcdfeghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_-': answer_text.text += key # Delete last character, if there are any chars at all elif key == 'backspace' and len(answer_text.text) > 0: answer_text.text = answer_text.text[:-1] # Stop collecting response and return it elif key == 'return': expName = answer_text.text print ('expName IN here: ', expName) now = False # Show current answer state instruction_text.draw() answer_text.draw() square1.draw() #have to draw trigger squ; otherwise transient white will happen$$$$$$$$$$$$$ square2.draw() win.flip() #setting name of file which will be used to save order of vs stim displayed; date = datetime.today().strftime('%Y%m%d_%H%M%S') #extract today's date fileName = expName + '_vs_Rf6x8' + date #loop over each stim and display it for rep in range(len(index)*repetition): #will loop around for total Repetitions (96*repetition) tic = clock.getTime() stim_ind = rep % len(index) #give a number between 0 and 95 which represents each stimuli, allowing to continuouly loop around for total repetitions #assign postion of stimulus i, j = stim_order[index[stim_ind]][1], stim_order[index[stim_ind]][2] #assing colour of stimulus colour = stim_order[index[stim_ind]][3] #Create stimulus with changing : a single rect with x = screenwdth/8 and y = screenheight/6 stim = visual.ShapeStim( win = win, units = "norm", pos = (i * (1.0/12.0) , j * (-1.0/3.0)), #moves the stim by 1/9th to the right and 1/4th down (relative to screen size); if (i,j) = (0,0); display middle screen @ top left corner fillColor = colour, vertices = stim_vertices, lineWidth = 0 ) #save vs data in .csv format #create a temp list variable that stores array values that will be appended save_row = stim_order[index[stim_ind]].tolist() #open and append values to new file with open(fileName + '.csv', 'a') as f: for i in range(len(save_row)): f.write(str(save_row[i]) + ',') f.write('\n') #Display stimulation using a series of while loops win.color = winClr square1.draw() square2.draw() win.flip() #time before the stimulation toc = clock.getTime() - tic while toc < (t_before/1000.0): toc = clock.getTime() - tic #this if statement is for existing the stimulation if mouse.getPressed()[1]: return #display trigger squares square1.draw() square2.draw() win.flip() #t_triger initial timing for triggerin the camera for i in range(int(FR*MovSinGrat_t_triginit/1000.0)): if mouse.getPressed()[1]: return if i < 3: square1.fillColor = [1,1,1] square2.fillColor = [-1,-1,-1] else: square1.fillColor = [-1,-1,-1] square2.fillColor = [-1,-1,-1] win.color = winClr square1.draw() square2.draw() win.flip() #making the top square white square1.fillColor = [-1,-1,-1] square2.fillColor = [1,1,1] #drawing the stimulus on the window for frm in range(int(FR*t_during/1000.0)): if mouse.getPressed()[1]: return stim.draw() square1.draw() square2.draw() win.flip() #changing the characteristics of the two squares at the bottom left corner square1.fillColor = [-1,-1,-1] square2.fillColor = [-1,-1,-1] #time after the stimulation for toc in range(int(t_after*FR/1000.0)): #win.color = winClr square1.draw() square2.draw() win.flip()