views.py 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292
  1. import time
  2. import math
  3. import json
  4. from django.core.urlresolvers import reverse
  5. from django.http import HttpResponseRedirect, HttpResponse
  6. from django.contrib import messages
  7. from django.core.cache import cache
  8. from django.conf import settings
  9. from mongoengine import ValidationError
  10. from bson.objectid import ObjectId
  11. from multiprocessing import Process
  12. from .models import SpriteMetaData
  13. from .service import SliceGenerator, SubvolumeCreator
  14. from ..models import Volume
  15. from ..views import handleException
  16. from visualization.mongodb import gridfshelper
  17. from datetime import datetime, timedelta
  18. import logging
  19. logger = logging.getLogger(__name__)
  20. def generateslice(request, id):
  21. if request.method != 'POST':
  22. messages.error(request, 'no post')
  23. return HttpResponseRedirect(reverse('volumes:show', args=(id,)))
  24. try:
  25. volume = Volume.objects(id=id)[0]
  26. except (IndexError, ValidationError) as e:
  27. return handleException(request, id, e)
  28. volume.generateSlicesStatus = 'running'
  29. volume.save()
  30. process = Process(target=SliceGenerator.sliceGenerator, args=(request, volume.id,))
  31. process.start()
  32. # just for testing and using pdb, using the same thread
  33. # SliceGenerator.sliceGenerator(request, volume.id)
  34. messages.info(request, 'generating textures, please wait and refresh from time to time')
  35. return HttpResponseRedirect(reverse('volumes:show', args=(id,)))
  36. def getSubvolume(request, id, x, y, z, t, depth, requestedRes, testId=None):
  37. starttime = time.time()
  38. try:
  39. volume = Volume.objects(id=id)[0]
  40. except (IndexError, ValidationError) as e:
  41. return handleException(request, id, e)
  42. x = int(x)
  43. y = int(y)
  44. z = int(z)
  45. t = int(t)
  46. depth = int(depth)
  47. if t >= len(volume.rawFrames) or t < 0:
  48. t = 0
  49. rawFrame = volume.rawFrames[t]
  50. sizex = rawFrame.originalSize.sizex
  51. sizey = rawFrame.originalSize.sizey
  52. sizez = rawFrame.originalSize.sizez
  53. if testId is None:
  54. ''' are there any sprites within 30pixels around the point ? '''
  55. spriteMetaDatas = SpriteMetaData.objects(
  56. x__gte=(x-sizex/10),
  57. x__lte=(x+sizex/10),
  58. y__gte=(y-sizey/10),
  59. y__lte=(y+sizey/10),
  60. z__gte=(z-sizez/10),
  61. z__lte=(z+sizez/10),
  62. depth=depth,
  63. volumeId=id
  64. )
  65. ''' found a generated sprite in the near of the clicked point, just using it '''
  66. if len(spriteMetaDatas) > 0:
  67. for spriteMetaData in spriteMetaDatas:
  68. spritefilename = '%s.%s' % (str(spriteMetaData.spriteId), spriteMetaData.format)
  69. if cache.get(spritefilename) is not None:
  70. return HttpResponse(spriteMetaData.jsonInformation, content_type='json')
  71. else:
  72. spriteMetaData.delete()
  73. ''' end testId is None '''
  74. spriteId = ObjectId()
  75. format = 'jpeg'
  76. ''' metadata information for this sprite'''
  77. now = datetime.now()
  78. spriteMetaData = SpriteMetaData()
  79. spriteMetaData.creationTime = now
  80. spriteMetaData.spriteId = str(spriteId)
  81. spriteMetaData.format = format
  82. spriteMetaData.volumeId = str(id)
  83. spriteMetaData.x = x
  84. spriteMetaData.y = y
  85. spriteMetaData.z = z
  86. spriteMetaData.t = t
  87. spriteMetaData.depth = depth
  88. ''' caluclating dimensions '''
  89. ''' zoom factor is calucated by 2 * depth '''
  90. zoomFactor = 2
  91. zoomFactor *= depth
  92. minWidth = int(math.floor(sizex / zoomFactor))
  93. ''' lower bound set to 300 pxs '''
  94. if minWidth < 300:
  95. minWidth = 300
  96. minWidthHalf = int(math.floor(minWidth / 2))
  97. numberOfLayers = minWidth # we want it to be cube
  98. sqrtZ = int(math.floor(math.sqrt(numberOfLayers)))
  99. numberOfLayers = int(math.pow(sqrtZ, 2))
  100. ''' error prevention let us not run out of the volume '''
  101. if numberOfLayers > rawFrame.originalSize.sizez:
  102. numberOfLayers = rawFrame.originalSize.sizez
  103. sqrtZ = int(math.floor(math.sqrt(numberOfLayers)))
  104. numberOfLayers = int(math.pow(sqrtZ, 2))
  105. minWidth = numberOfLayers
  106. minWidthHalf = int(math.floor(minWidth / 2))
  107. numberOfLayersHalf = int(math.floor(numberOfLayers / 2))
  108. ''' set borders correctly '''
  109. if ((x - minWidthHalf) < 0):
  110. x = 0
  111. elif x + minWidthHalf > rawFrame.originalSize.sizex:
  112. x = rawFrame.originalSize.sizex - minWidth
  113. else:
  114. x = x - minWidthHalf
  115. if y - minWidthHalf < 0:
  116. y = 0
  117. elif y + minWidthHalf > rawFrame.originalSize.sizey:
  118. y = rawFrame.originalSize.sizey - minWidth
  119. else:
  120. y = y - minWidthHalf
  121. print('originalsize in z %d' % rawFrame.originalSize.sizez)
  122. if z - numberOfLayersHalf < 0:
  123. z = 0
  124. elif z + numberOfLayersHalf > rawFrame.originalSize.sizez:
  125. z = rawFrame.originalSize.sizez - numberOfLayers
  126. else:
  127. z = z - numberOfLayersHalf
  128. '''
  129. creatorThread = SubvolumeCreator.SubvolumeCreator(volume.id, x, y, z, t, minWidth, sqrtZ, numberOfLayers, spriteId, format, starttime, testId)
  130. creatorThread.start()
  131. '''
  132. # requestedRes = int(request.session.get('requestedRes', 2048))
  133. # if requestedRes is None or requestedRes < 2048:
  134. # requestedRes = 2048
  135. requestedRes = int(requestedRes)
  136. creatorProcess = Process(
  137. target=SubvolumeCreator.subvolumeCreator,
  138. args=(
  139. volume.id,
  140. x,
  141. y,
  142. z,
  143. t,
  144. minWidth,
  145. sqrtZ,
  146. numberOfLayers,
  147. spriteId,
  148. format,
  149. requestedRes,
  150. starttime,
  151. testId,
  152. )
  153. )
  154. creatorProcess.start()
  155. infoObject = {}
  156. infoObject['slicesOverX'] = sqrtZ
  157. infoObject['slicesOverY'] = sqrtZ
  158. infoObject['numberOfSlices'] = numberOfLayers
  159. infoObject['spriteId'] = str(spriteId)
  160. infoObject['depth'] = depth
  161. infoObject['dimension'] = {}
  162. infoObject['dimension']['xmin'] = x
  163. infoObject['dimension']['ymin'] = y
  164. infoObject['dimension']['zmin'] = z
  165. infoObject['dimension']['xywidth'] = minWidth
  166. jsonString = json.dumps(infoObject)
  167. spriteMetaData.jsonInformation = jsonString
  168. spriteMetaData.save()
  169. return HttpResponse(jsonString, content_type='json')
  170. def getSubvolumeSprite(request, id, spriteId):
  171. return getSubvolumeFromCache(request, id, spriteId)
  172. '''return getSubvolumeFromGridFS(request, id, spriteId)'''
  173. def getSubvolumeFromGridFS(request, id, spriteId):
  174. filename = spriteId + '.jpeg'
  175. if gridfshelper.fileexists(filename):
  176. handle = gridfshelper.openfile(spriteId + '.jpeg')
  177. return HttpResponse(handle.read(), content_type='image/jpeg')
  178. else:
  179. return HttpResponse(None, content_type='image/jpeg')
  180. def getSubvolumeFromCache(request, id, spriteId):
  181. handle = cache.get(spriteId + '.jpeg')
  182. if handle is None:
  183. response = HttpResponse(None, content_type='image/jpeg')
  184. else:
  185. response = HttpResponse(handle, content_type='image/jpeg')
  186. response['Content-Length'] = len(handle)
  187. return response
  188. def subvolumeAvailable(request, id, spriteId):
  189. '''jsonstring = json.dumps({ 'available' : gridfshelper.fileexists(spriteId + '.jpeg') })'''
  190. jsonstring = json.dumps({'available': cache.get(spriteId + '.jpeg') is not None})
  191. return HttpResponse(jsonstring, content_type='json')
  192. def listfiles(request, id, plain=None):
  193. try:
  194. spriteMetaDatas = SpriteMetaData.objects()
  195. except (IndexError, ValidationError) as e:
  196. return handleException(request, id, e)
  197. print(plain)
  198. if plain is None:
  199. filenames = []
  200. for spriteMetaData in spriteMetaDatas:
  201. filenames.append(spriteMetaData.spriteId)
  202. else:
  203. filenames = gridfshelper.listfiles()
  204. print(filenames)
  205. jsonstring = json.dumps({'files': filenames})
  206. return HttpResponse(jsonstring, content_type='json')
  207. def deletefiles(request, id):
  208. try:
  209. spriteMetaDatas = SpriteMetaData.objects()
  210. except (IndexError, ValidationError) as e:
  211. return handleException(request, id, e)
  212. now = datetime.now()
  213. deleted = []
  214. kept = []
  215. minCachingTime = timedelta(seconds=settings.SUBVOLUME_CACHING_TIME)
  216. for spriteMetaData in spriteMetaDatas:
  217. timeDelta = now - spriteMetaData.creationTime
  218. if timeDelta > minCachingTime:
  219. deleted.append(spriteMetaData.getfilename())
  220. spriteMetaData.delete()
  221. else:
  222. kept.append(spriteMetaData.spriteId)
  223. return HttpResponse(
  224. json.dumps({
  225. 'deleted': deleted,
  226. 'kept': kept,
  227. 'minCachingTime(sec)': minCachingTime.total_seconds()
  228. }),
  229. content_type='json'
  230. )