run.py 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187
  1. # main imports
  2. import os
  3. import time
  4. import numpy as np
  5. import pickle
  6. import sys
  7. # django imports
  8. from django.conf import settings
  9. # module imports
  10. from ..utils import api
  11. from ..utils.processing import crop_images
  12. from .. import config as cfg
  13. # expe imports
  14. from .classes.quest_plus import QuestPlus
  15. from .classes.quest_plus import psychometric_fun
  16. # other imports
  17. from ipfml import utils
  18. from pprint import pprint
  19. def run_quest_one_image(request, model_filepath, output_file):
  20. # 1. get session parameters
  21. qualities = request.session.get('qualities')
  22. scene_name = request.session.get('scene')
  23. expe_name = request.session.get('expe')
  24. # by default
  25. iteration = 0
  26. # used to stop when necessary
  27. if 'iteration' in request.GET:
  28. iteration = int(request.GET.get('iteration'))
  29. else:
  30. request.session['expe_started'] = False
  31. # 2. Get expe information if started
  32. # first time only init `quest`
  33. # if experiments is started we can save data
  34. if request.session.get('expe_started'):
  35. # does not change expe parameters
  36. if request.session['expe_data']['expe_previous_iteration'] == iteration:
  37. return None
  38. else:
  39. current_expe_data = request.session['expe_data']
  40. answer = int(request.GET.get('answer'))
  41. expe_answer_time = time.time() - current_expe_data['expe_answer_time']
  42. previous_percentage = current_expe_data['expe_percentage']
  43. previous_orientation = current_expe_data['expe_orientation']
  44. previous_position = current_expe_data['expe_position']
  45. previous_stim = current_expe_data['expe_stim']
  46. print("Answer time is ", expe_answer_time)
  47. # 3. Load or create Quest instance
  48. # default params
  49. # TODO : add specific thresholds information for scene
  50. #thresholds = np.arange(50, 10000, 50)
  51. stim_space = np.asarray(qualities)
  52. slope_range = cfg.expes_configuration[expe_name]['params']['slopes'][scene_name]
  53. slopes = np.arange(slope_range[0], slope_range[1], slope_range[2])
  54. #slopes = np.arange(0.0001, 0.001, 0.00003) # contemporary
  55. #slopes = np.arange(0.0005, 0.01, 0.0003) # bathroom
  56. #slopes = np.arange(1.995,19.95,0.5985)
  57. # TODO : update norm slopes
  58. # stim_space = np.asarray(qualities)
  59. # slopes = np.arange(0.0001, 0.001, 0.00003)
  60. # # normalize stim_space and slopes for this current scene
  61. # stim_space_norm = np.array(utils.normalize_arr_with_range(stim_space, stim_space.min(), stim_space.max()))
  62. # slopes_norm = slopes * (slopes.max() - slopes.min())
  63. # check if necessary to construct `quest` object
  64. if not os.path.exists(model_filepath):
  65. print('Creation of `qp` model')
  66. #print(slopes_norm)
  67. #qp = QuestPlus(stim_space_norm, [stim_space_norm, slopes_norm], function=psychometric_fun)
  68. qp = QuestPlus(stim_space, [stim_space, slopes], function=psychometric_fun)
  69. else:
  70. print('Load `qp` model')
  71. filehandler = open(model_filepath, 'rb')
  72. qp = pickle.load(filehandler)
  73. pprint(qp)
  74. # 4. If expe started update and save experiments information and model
  75. # if experiments is already began
  76. if request.session.get('expe_started'):
  77. # TODO : update norm slopes
  78. #previous_stim_norm = (int(previous_stim) - stim_space.min()) / (stim_space.max() - stim_space.min() + sys.float_info.epsilon)
  79. print(previous_stim)
  80. #print(previous_stim_norm)
  81. qp.update(int(previous_stim), answer)
  82. entropy = qp.get_entropy()
  83. print('chosen entropy', entropy)
  84. line = str(previous_stim)
  85. line += ";" + scene_name
  86. line += ";" + str(previous_percentage)
  87. line += ";" + str(previous_orientation)
  88. line += ";" + str(previous_position)
  89. line += ";" + str(answer)
  90. line += ";" + str(expe_answer_time)
  91. line += ";" + str(entropy)
  92. line += '\n'
  93. output_file.write(line)
  94. output_file.flush()
  95. if entropy < cfg.expes_configuration[expe_name]['params']['entropy']:
  96. request.session['expe_finished'] = True
  97. return None
  98. # 5. Contruct new image and save it
  99. # construct image
  100. if iteration < cfg.expes_configuration[expe_name]['params']['iterations']:
  101. # process `quest`
  102. next_stim = qp.next_contrast()
  103. print(next_stim)
  104. #next_stim_img = int(next_stim*(stim_space.max()-stim_space.min())+stim_space.min())
  105. print('-------------------------------------------------')
  106. print('Iteration', iteration)
  107. print(next_stim)
  108. #print('denorm', next_stim_img)
  109. print('-------------------------------------------------')
  110. #noisy_image = api.get_image(scene_name, next_stim_img)
  111. noisy_image = api.get_image(scene_name, next_stim)
  112. # reconstruct reference image from list stored into session
  113. ref_image = api.get_image(scene_name, 'max')
  114. img_merge, percentage, orientation, position = crop_images(noisy_image, ref_image)
  115. else:
  116. request.session['expe_finished'] = True
  117. return None
  118. # save image using user information
  119. # create output folder for tmp files if necessary
  120. tmp_folder = os.path.join(settings.MEDIA_ROOT, cfg.output_tmp_folder)
  121. if not os.path.exists(tmp_folder):
  122. os.makedirs(tmp_folder)
  123. # generate tmp merged image (pass as BytesIO was complicated..)
  124. filepath_img = os.path.join(tmp_folder, request.session.get('id') + '_' + scene_name + '' + expe_name + '.png')
  125. # replace img_merge if necessary (new iteration of expe)
  126. if img_merge is not None:
  127. img_merge.save(filepath_img)
  128. # save qp model at each iteration
  129. file_pi = open(model_filepath, 'wb')
  130. pickle.dump(qp, file_pi)
  131. # 6. Prepare experiments data for current iteration and data for view
  132. # here you can save whatever you need for you experiments
  133. data_expe = {
  134. 'image_path': filepath_img,
  135. 'expe_percentage': percentage,
  136. 'expe_orientation': orientation,
  137. 'expe_position': position,
  138. 'expe_answer_time': time.time(),
  139. 'expe_previous_iteration': iteration,
  140. 'expe_stim': str(next_stim)
  141. }
  142. # expe is now started
  143. request.session['expe_started'] = True
  144. return data_expe