views.py 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240
  1. # django imports
  2. from django.shortcuts import render
  3. from django.http import HttpResponse
  4. from django.conf import settings
  5. from django.contrib.auth.decorators import login_required
  6. from django.http import Http404
  7. # main imports
  8. import os
  9. import json
  10. import base64
  11. import random
  12. import numpy as np
  13. from datetime import datetime
  14. import pickle
  15. import time
  16. import zipfile
  17. from io import StringIO
  18. # expe imports
  19. from .expes.quest_plus import QuestPlus
  20. from .expes.quest_plus import psychometric_fun
  21. from .expes.run import run_quest_one_image
  22. # image processing imports
  23. import io
  24. from PIL import Image
  25. # module imports
  26. from .utils import api
  27. from .utils import functions
  28. from .utils.processing import crop_images
  29. from . import config as cfg
  30. def expe_list(request):
  31. # get all scenes from dataset
  32. scenes = api.get_scenes()
  33. # get list of experiences
  34. expes = cfg.expe_name_list
  35. # by default user restart expe
  36. request.session['expe_started'] = False
  37. return render(request, 'expe/expe_list.html', {'scenes': scenes, 'expes': expes})
  38. def indications(request):
  39. # get param
  40. expe_name = request.GET.get('expe')
  41. # expe parameters
  42. data = {
  43. 'expe_name': expe_name,
  44. 'question': cfg.expes_configuration[expe_name]['text']['question'],
  45. 'indication': cfg.expes_configuration[expe_name]['text']['indication']
  46. }
  47. return render(request, 'expe/expe_indications.html', data)
  48. # Create your views here.
  49. def expe(request):
  50. # get param
  51. expe_name = request.GET.get('expe')
  52. scene_name = request.GET.get('scene')
  53. # default filepath name
  54. filepath_img = ''
  55. # unique user ID during session (user can launch multiple exeperiences)
  56. if 'id' not in request.session:
  57. request.session['id'] = functions.uniqueID()
  58. # first time expe is launched add expe information
  59. if 'expe' not in request.session or expe_name != request.session.get('expe'):
  60. refresh_data(request, expe_name, scene_name)
  61. # refresh if scene_name changed
  62. if 'scene' not in request.session or scene_name != request.session.get('scene'):
  63. refresh_data(request, expe_name, scene_name)
  64. # create output folder for expe_result
  65. current_day = datetime.strftime(datetime.utcnow(), "%Y-%m-%d")
  66. results_folder = os.path.join(settings.MEDIA_ROOT, cfg.output_expe_folder_name_day.format(expe_name, current_day))
  67. if not os.path.exists(results_folder):
  68. os.makedirs(results_folder)
  69. result_filename = scene_name + '_' + request.session.get('id') + '_' + request.session.get('timestamp') +".csv"
  70. results_filepath = os.path.join(results_folder, result_filename)
  71. if not os.path.exists(results_filepath):
  72. output_file = open(results_filepath, 'w')
  73. functions.write_header_expe(output_file, expe_name)
  74. else:
  75. output_file = open(results_filepath, 'a')
  76. # create `quest` object if not exists
  77. models_folder = os.path.join(settings.MEDIA_ROOT, cfg.model_expe_folder.format(expe_name, current_day))
  78. if not os.path.exists(models_folder):
  79. os.makedirs(models_folder)
  80. model_filename = result_filename.replace('.csv', '.obj')
  81. model_filepath = os.path.join(models_folder, model_filename)
  82. # run `quest` expe
  83. img_merge = run_quest_one_image(request, model_filepath, output_file)
  84. if not request.session.get('expe_finished'):
  85. # create output folder for tmp files if necessary
  86. tmp_folder = os.path.join(settings.MEDIA_ROOT, cfg.output_tmp_folder)
  87. if not os.path.exists(tmp_folder):
  88. os.makedirs(tmp_folder)
  89. # generate tmp merged image (pass as BytesIO was complicated..)
  90. # TODO : add crontab task to erase generated img
  91. filepath_img = os.path.join(tmp_folder, request.session.get('id') + '_' + scene_name + '' + expe_name + '.png')
  92. img_merge.save(filepath_img)
  93. else:
  94. # reinit session as default value
  95. del request.session['expe']
  96. del request.session['scene']
  97. del request.session['qualities']
  98. del request.session['timestamp']
  99. # expe parameters
  100. data = {
  101. 'expe_name': expe_name,
  102. 'img_merged_path': filepath_img,
  103. 'end_text': cfg.expes_configuration[expe_name]['text']['end_text']
  104. }
  105. return render(request, 'expe/expe.html', data)
  106. @login_required(login_url="login/")
  107. def list_results(request, expe=None):
  108. """
  109. Return all results obtained from experiences
  110. """
  111. if expe is None:
  112. folders = cfg.expe_name_list
  113. else:
  114. if expe in cfg.expe_name_list:
  115. folder_path = os.path.join(settings.MEDIA_ROOT, cfg.output_expe_folder, expe)
  116. # init folder dictionnary
  117. folders = {}
  118. print(folder_path)
  119. if os.path.exists(folder_path):
  120. days = os.listdir(folder_path)
  121. print(days)
  122. folder = {}
  123. for day in days:
  124. day_path = os.path.join(folder_path, day)
  125. filenames = os.listdir(day_path)
  126. print(filenames)
  127. folders[day] = filenames
  128. else:
  129. raise Http404("Expe does not exists")
  130. return render(request, 'expe/expe_results.html', {'expe': expe, 'folders': folders})
  131. @login_required(login_url="login/")
  132. def getfiles(request):
  133. day = request.POST.get('day')
  134. # get files from a specific day
  135. folder_path = os.path.join(settings.MEDIA_ROOT, cfg.model_expe_folder.format(day))
  136. filenames = os.listdir(folder_path)
  137. # Folder name in ZIP archive which contains the above files
  138. # E.g [thearchive.zip]/somefiles/file2.txt
  139. # FIXME: Set this to something better
  140. zip_subdir = "somefiles"
  141. zip_filename = "%s.zip" % zip_subdir
  142. # Open StringIO to grab in-memory ZIP contents
  143. s = StringIO.StringIO()
  144. # The zip compressor
  145. zf = zipfile.ZipFile(s, "w")
  146. for fpath in filenames:
  147. # Calculate path for file in zip
  148. fdir, fname = os.path.split(fpath)
  149. zip_path = os.path.join(zip_subdir, fname)
  150. # Add file, at correct path
  151. zf.write(fpath, zip_path)
  152. # Must close zip for all contents to be written
  153. zf.close()
  154. # Grab ZIP file from in-memory, make response with correct MIME-type
  155. resp = HttpResponse(s.getvalue(), mimetype = "application/x-zip-compressed")
  156. # ..and correct content-disposition
  157. resp['Content-Disposition'] = 'attachment; filename=%s' % zip_filename
  158. return resp
  159. def refresh_data(request, expe_name, scene_name):
  160. '''
  161. Utils method to refresh data from session
  162. '''
  163. request.session['expe'] = expe_name
  164. request.session['scene'] = scene_name
  165. request.session['expe_started'] = False
  166. request.session['expe_finished'] = False
  167. request.session['qualities'] = api.get_scene_qualities(scene_name)
  168. # update unique timestamp each time new experience is launched
  169. request.session['timestamp'] = datetime.strftime(datetime.utcnow(), "%Y-%m-%d_%Hh%Mm%Ss")
  170. # TODO : add in cache ref_image
  171. # get reference image
  172. #ref_image = api.get_image(scene_name, 'max')
  173. # save ref image as list (can't save python object)
  174. #request.session['ref_img'] = np.array(ref_image).tolist()