Advertisement
Guest User

Untitled

a guest
Apr 25th, 2019
99
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 18.01 KB | None | 0 0
  1. #!/usr/bin/env python2
  2. # -*- coding: utf-8 -*-
  3.  
  4. from psychopy import visual, event, core
  5. from Tkinter import *
  6. import random
  7. import datetime
  8. import time
  9. import os
  10. import unicodedata
  11. import multiprocessing as mp
  12. import serial
  13. import csv
  14. import re
  15. import pygame
  16.  
  17. ################################################################
  18. #
  19. # SETTINGS
  20. #
  21. ################################################################
  22. # ### MONITOR AND WINDOW
  23.  
  24. # for debugging process it is recomendened not to use fulscreen
  25. fullscr = True
  26. color_background = [0, 0, 0]
  27.  
  28. # width and height of the window in pixels (it matters only if fullscr == False
  29. win_width, win_height = 1366, 768
  30. #win_width, win_height = 1000, 600
  31.  
  32. # ### END OF MONITOR AND WINDOW
  33. ################################
  34.  
  35. ################################
  36. # ### STIMULI SETTINGS
  37.  
  38. group = 1 #1/2 1 - no background; 2 - with background
  39. fontsize_instruction = 35
  40. color_font = 'white'
  41. bolded_font = False
  42. word_index = 0
  43.  
  44. # time before first stimulus appears, after instruction (in seconds) ## !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  45. init_gap_time = 0#2.0
  46.  
  47. # stimulus display time
  48. stim_time = 0.5 #5
  49.  
  50. # Inter Trial Interval, time between stimuli
  51. iti = 0.5 #2
  52. #iti = 0
  53.  
  54. # ### END OF STIMULI SETTINGS
  55. ################################ c mcm, kmfk
  56.  
  57. ################################################################
  58. #
  59. # END of SETTINGS
  60. #
  61. ################################################################
  62.  
  63.  
  64. ################################################################
  65. #
  66. # PRELIMINARIES
  67. #
  68. ################################################################
  69.  
  70. ################################
  71. # ### FUNCTION BOARD
  72.  
  73.  
  74. def move_on():
  75. global keys_list
  76. while True:
  77. keys_list = event.getKeys()
  78. if 'space' in keys_list:
  79. break
  80. elif 'escape' in keys_list:
  81. mywin.close()
  82. core.quit()
  83. break
  84.  
  85. def create_slide(entry, color, height, x, y):
  86. text = {'intro': u'Przeczytaj uważnie instrukcję i postępuj zgodnie ze wskazówkami w niej zawartymi przez cały czas trwania badania.\n\nAby przejść dalej naciśnij spację',
  87. 'intro2': u'Na ekranie będą pokazywane różne postacie. Twoim zadaniem jest przyglądanie się wyświetlanym obrazom, a następnie udzielenie odpowiedzi na pojawiające się pytania przy pomocy myszki. \n\nNie ma dobrych i złych odpowiedzi. W razie niepewności kieruj się pierwszą myślą. Każda postać pojawi się 3 razy. \n\nAby przejść dalej naciśnij spację',
  88. 'intro3': u'Na początku, na końcu oraz pomiędzy obrazami będzie wyświetlany punkt fiksacyjny. W miarę możliwości, spoglądaj na niego.\n\nAby rozpocząć eksperyment naciśnij spację',
  89. 'ready': u'Połóż rękę na myszce i przygotuj się',
  90. 'question1':u'Na ile prezentowany model jest podobny do człowieka?',
  91. 'question2':u'Na ile łatwo było Ci odpowiedzieć na poprzednie pytanie?',
  92. 'question3':u'Oceń na ile komfortowo czujesz się oglądając model w prezentowanym środowisku:',
  93. 'question4':u'Jaka jest twoja emocjonalna reakcja na prezentowany model?',
  94. 'ans10': u'(1) zupełnie \nniepodobny do \nczłowieka',
  95. 'ans11': u'(2) raczej \nniepodobny do \nczłowieka',
  96. 'ans12': u'(3) zaczyna \nprzypominać \nczłowieka',
  97. 'ans13': u'(4) raczej \npodobny do \nczłowieka',
  98. 'ans14': u'(5) bardzo \npodobny do \nczłowieka',
  99. 'ans20': u'(1) bardzo \nłatwo' ,
  100. 'ans21': u'(2) łatwo',
  101. 'ans22': u'(3) trudno',
  102. 'ans23': u'(4) bardzo \ntrudno',
  103. 'ans30': u'(1) bardzo \nkomfortowo',
  104. 'ans31': u'(2) dość \nkomfortowo',
  105. 'ans32': u'(3) neutralnie',
  106. 'ans33': u'(4) niekomfortowo',
  107. 'ans34': u'(5) bardzo \nniekomfortowo',
  108. 'ans40': u'Model wzbudza \nmój niepokój',
  109. 'ans41': u'Neutralna',
  110. 'ans42': u'Model wzbudza \nsympatię',
  111. 'empty': '',
  112. 'fix':'+',
  113. 'end': u'Koniec eksperymentu. Dziękujemy za udział w badaniu. \n\nProszę, wypełnij dane osobowe w okienku.'
  114. }
  115.  
  116. aslide = visual.TextStim(
  117. win=mywin,
  118. text=text[entry], font='Monospace', wrapWidth=win_width*0.9,
  119. # instruction text wrap is 90% of the window width
  120. pos=(x, y), height=height,
  121. color=color, bold=bolded_font
  122. )
  123. return aslide
  124.  
  125. def create_boxes(quantity, y, answer):
  126. boxes = []
  127. color = (0.6,0.6,0.6)
  128. x = -250
  129. if quantity == 5:
  130. x = -500
  131. elif quantity == 4:
  132. x = -375
  133. for i in range(quantity):
  134. if i == answer:
  135. color = (1, 1, 0)
  136. else:
  137. color = (0.6,0.6,0.6)
  138. boxes.append(visual.ShapeStim(mywin, units='pix', lineWidth=2, lineColor='white', lineColorSpace='rgb',
  139. fillColor=color, fillColorSpace='rgb', vertices=((120, 60), (120, -60), (-120, -60), (-120, 60)),
  140. pos=(x, y), size=1, ori=0.0, opacity=1.0, contrast=1.0, depth=1))
  141. boxes[i].draw()
  142. x += 250
  143. return boxes
  144.  
  145. def create_quest(number, quantity, height):
  146. ans = []
  147. x = -250
  148. if quantity == 5:
  149. x = -500
  150. elif quantity == 4:
  151. x = -375
  152. question = create_slide('question'+str(number), 'black', 32, 0, height); question.draw();
  153. for i in range(quantity):
  154. ans.append(create_slide('ans'+str(number)+str(i), 'black', 24, x, height-100))
  155. ans[i].draw();
  156. x += 250
  157.  
  158. def check_pressed(quantity, boxes):
  159. pressed = None
  160. stop = False
  161. for i in range(quantity):
  162. if mouse.isPressedIn(boxes[i],buttons=[0]):
  163. pressed = i
  164. stop = True
  165. return [stop, pressed]
  166.  
  167. def create_image(path):
  168. image = visual.ImageStim(
  169. win=mywin,
  170. image=path, mask=None, units='',
  171. pos=(0.0, 0.0), size=[1366,768], ori=0.0, color=(1.0, 1.0, 1.0), colorSpace='rgb',
  172. contrast=1.0, opacity=1.0, depth=0, interpolate=False, flipHoriz=False,
  173. flipVert=False, texRes=128, name=None, autoLog=None, maskParams=None
  174. )
  175. return image
  176.  
  177. def check_close():
  178. keys_list = event.getKeys()
  179. if not keys_list:
  180. pass
  181. if 'escape' in keys_list:
  182. mywin.close()
  183. core.quit()
  184.  
  185.  
  186. def output_creator(num, flag, quit):
  187. out_path = "GSR_data/"+str(num.get())+"_GSR.csv"
  188. while quit.empty():
  189. ser = serial.Serial('/dev/ttyACM0', 9600)
  190. data = ser.readline().decode("utf-8")
  191. with open(out_path, 'a') as out_file:
  192. try:
  193. out_file.write(re.sub("[^0-9]", "", data)+","+str(int(flag.value))+"\n")
  194. except OSError:
  195. print "No file"
  196. ser.close()
  197.  
  198. # ### END OF FUNCTION BOARD
  199. ################################
  200.  
  201. ################################################################
  202. #
  203. # END OF PRELIMINARIES
  204. #
  205. ################################################################
  206.  
  207. out_path = "Dane.csv"
  208. resp_number = ""
  209. with open(out_path, 'a+') as out_file:
  210. if os.stat("Dane.csv").st_size == 0:
  211. resp_number = "1"
  212. else:
  213. reader = csv.reader(out_file, delimiter=",")
  214. num = ""
  215. for row in reader:
  216. num = row[0]
  217. resp_number = str(int(float(row[0])+1))
  218.  
  219. out_path2 = "GSR_data/"+str(resp_number)+"_GSR.csv"
  220. with open(out_path2, 'a') as out_file2:
  221. try:
  222. out_file2.write("GSR, stim_present\n")
  223. except OSError:
  224. print "No file"
  225.  
  226.  
  227. resp_n = mp.Queue()
  228. quit = mp.Queue()
  229. flag = mp.Value('i', 0)
  230. proc = mp.Process(target=output_creator, args=(resp_n, flag, quit))
  231. resp_n.put(resp_number)
  232. proc.start()
  233.  
  234. ################################
  235. # ### GENERATE STIMULI
  236.  
  237. no_background = ["model01.png", "model02.png", "model03.png", "model04.png", "model05.png", "model06.png", "model07.png",
  238. "model08.png", "model09.png", "model10.png", "model11.png", "model12.png"]
  239.  
  240. with_background = ["model01b.png", "model02b.png", "model03b.png", "model04b.png", "model05b.png", "model06b.png", "model07b.png",
  241. "model08b.png", "model09b.png", "model10b.png", "model11b.png", "model12b.png"]
  242.  
  243. answers = []
  244. stim_nr = 0
  245. order_output = []
  246.  
  247. SEED = int(time.time())
  248. random.seed(SEED)
  249. if group == 1:
  250. stimulus_list = no_background
  251. path = "no_background/"
  252. else:
  253. stimulus_list = with_background
  254. path = "with_backgrounds/"
  255. random.shuffle(stimulus_list)
  256.  
  257. # ### END OF GENERATE STIMULI
  258. ################################
  259.  
  260. ################################################################
  261. #
  262. # EXPERIMENT
  263. #
  264. ################################################################
  265.  
  266. # create main window
  267. mywin = visual.Window(
  268. [win_width, win_height],
  269. monitor='testMonitor',
  270. winType='pyglet',
  271. units='pix',
  272. fullscr=fullscr,
  273. colorSpace='rgb',
  274. rgb=color_background,
  275. allowGUI=True
  276. )
  277.  
  278. # code the time to name file or variable
  279. datetime = datetime.datetime.now().strftime("%Y.%m.%d (%H:%M)")
  280.  
  281. ################################
  282.  
  283. # ### INSTRUCTION
  284. slide = create_slide('intro', 'black', fontsize_instruction, 0, 0); slide.draw(); mywin.flip()
  285. move_on()
  286.  
  287. slide = create_slide('intro2', 'black', fontsize_instruction, 0, 0); slide.draw(); mywin.flip()
  288. move_on()
  289.  
  290. slide = create_slide('intro3', 'black', fontsize_instruction, 0, 0); slide.draw(); mywin.flip()
  291. move_on()
  292.  
  293. slide = create_slide('ready', 'black', fontsize_instruction, 0, 0); slide.draw(); mywin.flip()
  294. core.wait(4)
  295.  
  296. slide = create_slide('empty', 'white', fontsize_instruction, 0, 0); slide.draw(); mywin.flip()
  297. core.wait(0.5)
  298. # ### END OF INSTRUCTION
  299. ################################
  300.  
  301.  
  302. ################################
  303. # ### EXPERIMENTAL SESSION
  304. slide = create_slide('fix', 'black', fontsize_instruction, 0, 0); slide.draw(); mywin.flip()
  305. core.wait(10)
  306.  
  307. mouse = event.Mouse(visible=True, newPos=None, win=None)
  308.  
  309. for i in range(len(stimulus_list)):
  310. stimulus = path + stimulus_list[i]
  311. stim_nr = int(stimulus_list[i][5]+stimulus_list[i][6])
  312. order_output.append(stim_nr)
  313. ans =[]
  314. RTs = []
  315.  
  316. pressed1 = [False, 0]
  317. pressed2 = [False, 0]
  318.  
  319. image = create_image(stimulus); image.draw();mywin.flip()
  320. flag.value = stim_nr
  321. core.wait(stim_time)
  322.  
  323. boxes = create_boxes(5, 150, None)
  324. quest1 = create_quest(1, 5, 250)
  325. mywin.flip()
  326. flag.value = 0
  327. start = time.time()
  328. while True:
  329. check_close()
  330. pressed1 = check_pressed(5, boxes) #return [True, pressed number] if a box was pressed; [False, None] if not pressed
  331. #pressed1[1] = 1
  332. #core.wait(0.5)
  333. #pressed1[0] = True
  334. if pressed1[0]: #if a box was pressed, break the loop
  335. end = time.time()
  336. RTs.append("%.4f" % (end - start))
  337. ans.append(pressed1[1])
  338. break
  339. boxes = create_boxes(5, 150, pressed1[1])
  340. quest1 = create_quest(1, 5, 250)
  341. boxes = create_boxes(4, -150, None)
  342. quest2 = create_quest(2, 4, -50)
  343. mywin.flip()
  344. start = time.time()
  345. while True:
  346. check_close()
  347. pressed2 = check_pressed(4, boxes) #return [True, pressed number] if a box was pressed; [False, None] if not pressed
  348. #pressed2[1] = 1 #
  349. #core.wait(0.5)
  350. #pressed2[0] = True
  351. if pressed2[0]: #if a box was pressed, break the loop
  352. end = time.time()
  353. RTs.append("%.4f" % (end - start))
  354. ans.append(pressed2[1])
  355. break
  356. boxes = create_boxes(5, 150, pressed1[1])
  357. quest1 = create_quest(1, 5, 250)
  358. boxes = create_boxes(4, -150, pressed2[1])
  359. quest2 = create_quest(2, 4, -50)
  360. mywin.flip()
  361. core.wait(iti)
  362.  
  363. image.draw();mywin.flip()
  364. flag.value = stim_nr
  365. core.wait(stim_time)
  366.  
  367. boxes = create_boxes(5, 150, None)
  368. quest1 = create_quest(3, 5, 250)
  369. mywin.flip()
  370. flag.value = 0
  371. start = time.time()
  372. while True:
  373. check_close()
  374. pressed1 = check_pressed(5, boxes) #return [True, pressed number] if a box was pressed; [False, None] if not pressed
  375. #pressed1[1] = 1
  376. #core.wait(0.5)
  377. #pressed1[0] = True
  378. if pressed1[0]: #if a box was pressed, break the loop
  379. end = time.time()
  380. RTs.append("%.4f" % (end - start))
  381. ans.append(pressed1[1])
  382. break
  383. boxes = create_boxes(5, 150, pressed1[1])
  384. quest1 = create_quest(3, 5, 250)
  385. boxes = create_boxes(3, -150, None)
  386. quest2 = create_quest(4, 3, -50)
  387. mywin.flip()
  388. start = time.time()
  389. while True:
  390. check_close()
  391. pressed2 = check_pressed(3, boxes) #return [True, pressed number] if a box was pressed; [False, None] if not pressed
  392. #pressed2[1] = 1
  393. #core.wait(0.5)
  394. #pressed2[0] = True
  395. if pressed2[0]: #if a box was pressed, break the loop
  396. end = time.time()
  397. RTs.append("%.4f" % (end - start))
  398. ans.append(pressed2[1])
  399. break
  400. boxes = create_boxes(5, 150, pressed1[1])
  401. quest1 = create_quest(3, 5, 250)
  402. boxes = create_boxes(3, -150, pressed2[1])
  403. quest2 = create_quest(4, 3, -50)
  404. mywin.flip()
  405. core.wait(iti)
  406.  
  407. image.draw();mywin.flip()
  408. flag.value = stim_nr
  409. core.wait(stim_time)
  410.  
  411. slide = create_slide('fix', 'black', fontsize_instruction, 0, 0); slide.draw(); mywin.flip()
  412. flag.value = 0
  413. core.wait(iti)
  414. answers.append([stimulus_list[i],ans,RTs])
  415.  
  416. slide = create_slide('fix', 'black', fontsize_instruction, 0, 0); slide.draw(); mywin.flip()
  417. core.wait(10)
  418.  
  419. #####################################
  420. ### closing GSR data collection
  421. quit.put(1)
  422. resp_n.close()
  423. quit.close()
  424. proc.terminate()
  425. ###
  426. #####################################
  427.  
  428. slide = create_slide('end', 'black', fontsize_instruction, 0, 0); slide.draw(); mywin.flip()
  429. core.wait(5)
  430. mywin.winHandle.minimize()
  431. mywin.winHandle.set_fullscreen(False)
  432.  
  433. # ### END OF EXPERIMENTAL SESSION
  434. ################################
  435.  
  436. ################################################################
  437. #
  438. # CSV OUTPUT & EXTERNAL DATA
  439. #
  440. ################################################################
  441.  
  442. ################################
  443. # ### EXTERNAL DATA
  444. def button_action(event):
  445. global age, gender, educ, field
  446. age = entryAge.get()
  447. gender = entryGender.get()
  448. educ = entryEduc.get()
  449. field = entryField.get()
  450. if age != '' and gender != '' and educ != '' and field != '':
  451. masterTK.destroy()
  452.  
  453. masterTK = Tk()
  454. masterTK.title(u"Dane osobowe")
  455. masterTK.resizable(width=None, height=None)
  456. mainFrame = Frame(masterTK)
  457.  
  458. labelFrame = Frame(mainFrame)
  459. L = Label(labelFrame, text=u"Płeć: ", anchor=E).pack(fill=X)
  460. L = Label(labelFrame, text=u"Wiek: ", anchor=E).pack(fill=X)
  461. L = Label(labelFrame, text=u"Wykształcenie: ", anchor=E).pack(fill=X)
  462. L = Label(labelFrame, text=u"Kierunek studiów (bieżący lub ukończony): ", anchor=E).pack(fill=X)
  463.  
  464. entryFrame = Frame(mainFrame)
  465. entryGender = Entry(entryFrame)
  466. entryGender.pack()
  467. entryGender.focus_set()
  468. entryAge = Entry(entryFrame)
  469. entryAge.pack()
  470. entryEduc = Entry(entryFrame)
  471. entryEduc.pack()
  472. entryField = Entry(entryFrame)
  473. entryField.pack()
  474.  
  475.  
  476. labelFrame.pack(side=LEFT)
  477. entryFrame.pack(side=LEFT)
  478. mainFrame.pack(side=TOP, expand=1, fill=X, padx=60, pady=5)
  479. button1 = Button(masterTK, text=u"Zakończ")
  480. button1.bind("<ButtonRelease-1>", button_action)
  481. masterTK.bind("<Return>", button_action)
  482.  
  483. button1.pack(side=BOTTOM)
  484.  
  485. masterTK.withdraw()
  486. masterTK.update_idletasks() # Update "requested size" from geometry manager
  487. x = (masterTK.winfo_screenwidth() - masterTK.winfo_reqwidth()) / 2
  488. y = (masterTK.winfo_screenheight() - masterTK.winfo_reqheight()) / 2
  489. masterTK.geometry("+%d+%d" % (x, y))
  490. masterTK.deiconify()
  491.  
  492. masterTK.mainloop()
  493.  
  494. # ### END OF EXTERNAL DATA
  495. ################################
  496.  
  497. #################################
  498. # ### OUTPUT OPTIMISATION (UNSHUFFLE)
  499.  
  500. order = list(range(len(stimulus_list)))
  501. random.seed(SEED)
  502. random.shuffle(order)
  503. output_list = [0] * len(stimulus_list) # empty list with right length
  504. for index, original_index in enumerate(order):
  505. output_list[original_index] = answers[index]
  506.  
  507. # ### END OF OUTPUT OPTIMISATION
  508. ################################
  509.  
  510. #################################
  511. # ### CSV OUTPUT
  512.  
  513. def no_poles(dirty_string):
  514. temp_string = ','.join(dirty_string).replace(u"\u0141", "L").replace(u"\u0142", "l")
  515. return unicodedata.normalize('NFKD', temp_string).encode('ascii', 'ignore')
  516.  
  517.  
  518. def generate_stimuli_headers(f_output_list):
  519. stimuli_headers = ["id", "data", "plec", "wiek", "wyksztalcenie", "kierunek", "grupa", "kolejnosc"]
  520. for x in range(len(f_output_list)):
  521. for n in range(4):
  522. stimuli_headers.append(f_output_list[x][0] + "_pyt"+str(n+1))
  523. for n in range(4):
  524. stimuli_headers.append(f_output_list[x][0] + "_RT"+str(n+1))
  525. return no_poles(stimuli_headers)
  526.  
  527. def generate_data_logs(f_output_list):
  528. data_log = [resp_number, datetime, gender, age, educ, field, str(group), str(order_output).replace(",", ";")]
  529. for x in range(len(f_output_list)):
  530. for n in range(4):
  531. data_log.append(str(f_output_list[x][1][n]))
  532. for n in range(4):
  533. data_log.append(str(f_output_list[x][2][n]))
  534. return no_poles(data_log)
  535.  
  536. with open(out_path, 'a') as out_file:
  537. try:
  538. if os.stat("Dane.csv").st_size == 0:
  539. out_file.write((generate_stimuli_headers(output_list))+'\n')
  540. out_file.write(generate_data_logs(output_list) + '\n')
  541. except OSError:
  542. print "No file"
  543.  
  544. core.quit()
  545.  
  546. # ### END OF CSV OUTPUT
  547. ################################
  548.  
  549. ################################################################
  550. #
  551. # END OF EXPERIMENT
  552. #
  553. ################################################################
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement