expe.py 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  1. # main imports
  2. import numpy as np
  3. import os
  4. import time
  5. from datetime import datetime
  6. import re
  7. # image processing imports
  8. from .processing import crop_images
  9. # expe imports
  10. from .quest_plus import QuestPlus
  11. # load `config` variables
  12. from .. import config as cfg
  13. # PARAMETERS of the psychometric function
  14. chance_level = 0 #e.g. chance_level should be 0.5 for 2AFC (Two-alternative forced choice) procedure
  15. threshold_prob = 1.-(1.-chance_level)/2.0 #the probability level at the threshold
  16. # quest_plus.py comes also with psychometric.py wich includes the definition of the weibull and weibull_db function
  17. # here I define the logistic function using the same template that works with the quest_plus implementation
  18. def logistic(x, params, corr_at_thresh=threshold_prob, chance_level=chance_level):
  19. # unpack params
  20. if len(params) == 3:
  21. THRESHOLD, SLOPE, lapse = params
  22. else:
  23. THRESHOLD, SLOPE = params
  24. lapse = 0.
  25. b = 4 * SLOPE
  26. a = -b * THRESHOLD
  27. return chance_level + (1 - lapse - chance_level) / (1 + np.exp(-(a + b*x)))
  28. # that's a wrapper function to specify wich psychometric function one we want to use for the QUEST procedure
  29. def psychometric_fun( x , params ):
  30. return logistic(x , params , corr_at_thresh=threshold_prob, chance_level=chance_level )
  31. #create results directory if not exist
  32. if not os.path.exists(cfg.output_expe_folder):
  33. os.makedirs(cfg.output_expe_folder)
  34. timestamp = datetime.strftime(datetime.utcnow(), "%Y-%m-%d_%Hh%Mm%Ss")
  35. filename += "online_ans" + timestamp +".csv"
  36. f = open(filename,"w")
  37. #orientation : 0 = vertical, 1 = horizontal
  38. #image_ref_position : 0 = right/bottom, 1 = left/up
  39. #answer : left = 1, right = 0
  40. f.write('stimulus' + ";" + "name_stimulus" + ";" + 'cropping_percentage' + ";" + 'orientation' + ';'
  41. + 'image_ref_position' + ';' + 'answer' + ';' + 'time_reaction' + ';' + 'entropy' + '\n')
  42. #k=np.linspace(50,20000,50)
  43. #k=k.astype(int)
  44. dd_sam=[]
  45. for i in range(len(files)):
  46. ff = [int(s) for s in re.findall(r'\d+', files[i])]
  47. dd_sam.append(ff[0])
  48. dd_sam=np.array(dd_sam)
  49. thresholds = np.arange(50, 10000, 50)
  50. stim_space=np.asarray(dd_sam)
  51. slopes = np.arange(0.0001, 0.001, 0.00003)
  52. #mywin = visual.Window([800,600], monitor="testMonitor", screen = 1, units="deg",fullscr=True)
  53. qp = QuestPlus(stim_space, [thresholds, slopes], function=psychometric_fun)
  54. answerTime=[]
  55. r=[]
  56. dataset = "contemporary"
  57. #image_ref = Image.open(data_folder + files[-1])
  58. image_ref = get_image(diran_domain_name, dataset, 10000)
  59. for i in range(5):
  60. next_stim = qp.next_contrast()
  61. print(next_stim)
  62. #next_idx = np.where(dd_sam==next_stim)
  63. #print(files[next_idx[0][0]])
  64. #image_path = data_folder + files[next_idx[0][0]]
  65. #current_image = Image.open(image_path)
  66. current_image= get_image(diran_domain_name, dataset, next_stim)
  67. crop_image, percentage, orientation, position = crop_images(image_ref, current_image)
  68. img = visual.ImageStim(win=mywin, image=crop_image)
  69. img.draw()
  70. mywin.flip()
  71. start = time.time()
  72. key_answer = event.waitKeys(keyList=["left","right"])
  73. end = time.time()
  74. answerTime.append(end-start)
  75. if key_answer == ['left']:
  76. answer = 1 #one image
  77. else:
  78. answer = 0 #two images
  79. r.append(answer)
  80. qp.update(dd_sam[i], answer)
  81. entropy = qp.get_entropy()
  82. print(entropy)
  83. f.write(str(next_stim) + ";" + dataset + ";" + str(percentage) + ";" + str(orientation) + ";"
  84. + str(position) + ";" + str(answer) + ";" + str(answerTime[-1]) + ";" + str(entropy) +'\n')
  85. f.flush()