/lib/galaxy/datatypes/images.py

https://bitbucket.org/cistrome/cistrome-harvard/ · Python · 348 lines · 240 code · 64 blank · 44 comment · 22 complexity · ad3dc532df84e93a9d26c8aa2393d0da MD5 · raw file

  1. """
  2. Image classes
  3. """
  4. import data
  5. import logging
  6. from galaxy.datatypes.binary import Binary
  7. from galaxy.datatypes.metadata import MetadataElement
  8. from galaxy.datatypes import metadata
  9. from galaxy.datatypes.sniff import *
  10. from galaxy.datatypes.util.image_util import *
  11. from urllib import urlencode, quote_plus
  12. import zipfile
  13. import os, subprocess, tempfile, imghdr
  14. try:
  15. import Image as PIL
  16. except ImportError:
  17. try:
  18. from PIL import Image as PIL
  19. except:
  20. PIL = None
  21. log = logging.getLogger(__name__)
  22. # TODO: Uploading image files of various types is supported in Galaxy, but on
  23. # the main public instance, the display_in_upload is not set for these data
  24. # types in datatypes_conf.xml because we do not allow image files to be uploaded
  25. # there. There is currently no API feature that allows uploading files outside
  26. # of a data library ( where it requires either the upload_paths or upload_directory
  27. # option to be enabled, which is not the case on the main public instance ). Because
  28. # of this, we're currently safe, but when the api is enhanced to allow other uploads,
  29. # we need to ensure that the implementation is such that image files cannot be uploaded
  30. # to our main public instance.
  31. class Image( data.Data ):
  32. """Class describing an image"""
  33. def set_peek( self, dataset, is_multi_byte=False ):
  34. if not dataset.dataset.purged:
  35. dataset.peek = 'Image in %s format' % dataset.extension
  36. dataset.blurb = data.nice_size( dataset.get_size() )
  37. else:
  38. dataset.peek = 'file does not exist'
  39. dataset.blurb = 'file purged from disk'
  40. def sniff( self, filename ):
  41. # First check if we can use PIL
  42. if PIL is not None:
  43. try:
  44. im = PIL.open( filename )
  45. im.close()
  46. return True
  47. except:
  48. return False
  49. else:
  50. if imghdr.what( filename ) is not None:
  51. return True
  52. else:
  53. return False
  54. class Jpg( Image ):
  55. file_ext = "jpeg"
  56. def sniff(self, filename, image=None):
  57. """Determine if the file is in jpg format."""
  58. return check_image_type( filename, ['JPEG'], image )
  59. class Png( Image ):
  60. file_ext = "png"
  61. def sniff(self, filename, image=None):
  62. """Determine if the file is in png format."""
  63. return check_image_type( filename, ['PNG'], image )
  64. class Tiff( Image ):
  65. file_ext = "tiff"
  66. def sniff(self, filename, image=None):
  67. """Determine if the file is in tiff format."""
  68. return check_image_type( filename, ['TIFF'], image )
  69. class Bmp( Image ):
  70. file_ext = "bmp"
  71. def sniff(self, filename, image=None):
  72. """Determine if the file is in bmp format."""
  73. return check_image_type( filename, ['BMP'], image )
  74. class Gif( Image ):
  75. file_ext = "gif"
  76. def sniff(self, filename, image=None):
  77. """Determine if the file is in gif format."""
  78. return check_image_type( filename, ['GIF'], image )
  79. class Im( Image ):
  80. file_ext = "im"
  81. def sniff(self, filename, image=None):
  82. """Determine if the file is in im format."""
  83. return check_image_type( filename, ['IM'], image )
  84. class Pcd( Image ):
  85. file_ext = "pcd"
  86. def sniff(self, filename, image=None):
  87. """Determine if the file is in pcd format."""
  88. return check_image_type( filename, ['PCD'], image )
  89. class Pcx( Image ):
  90. file_ext = "pcx"
  91. def sniff(self, filename, image=None):
  92. """Determine if the file is in pcx format."""
  93. return check_image_type( filename, ['PCX'], image )
  94. class Ppm( Image ):
  95. file_ext = "ppm"
  96. def sniff(self, filename, image=None):
  97. """Determine if the file is in ppm format."""
  98. return check_image_type( filename, ['PPM'], image )
  99. class Psd( Image ):
  100. file_ext = "psd"
  101. def sniff(self, filename, image=None):
  102. """Determine if the file is in psd format."""
  103. return check_image_type( filename, ['PSD'], image )
  104. class Xbm( Image ):
  105. file_ext = "xbm"
  106. def sniff(self, filename, image=None):
  107. """Determine if the file is in XBM format."""
  108. return check_image_type( filename, ['XBM'], image )
  109. class Xpm( Image ):
  110. file_ext = "xpm"
  111. def sniff(self, filename, image=None):
  112. """Determine if the file is in XPM format."""
  113. return check_image_type( filename, ['XPM'], image )
  114. class Rgb( Image ):
  115. file_ext = "rgb"
  116. def sniff(self, filename, image=None):
  117. """Determine if the file is in RGB format."""
  118. return check_image_type( filename, ['RGB'], image )
  119. class Pbm( Image ):
  120. file_ext = "pbm"
  121. def sniff(self, filename, image=None):
  122. """Determine if the file is in PBM format"""
  123. return check_image_type( filename, ['PBM'], image )
  124. class Pgm( Image ):
  125. file_ext = "pgm"
  126. def sniff(self, filename, image=None):
  127. """Determine if the file is in PGM format"""
  128. return check_image_type( filename, ['PGM'], image )
  129. class Eps( Image ):
  130. file_ext = "eps"
  131. def sniff(self, filename, image=None):
  132. """Determine if the file is in eps format."""
  133. return check_image_type( filename, ['EPS'], image )
  134. class Rast( Image ):
  135. file_ext = "rast"
  136. def sniff(self, filename, image=None):
  137. """Determine if the file is in rast format"""
  138. return check_image_type( filename, ['RAST'], image )
  139. class Pdf( Image ):
  140. file_ext = "pdf"
  141. def sniff(self, filename):
  142. """Determine if the file is in pdf format."""
  143. headers = get_headers(filename, None, 1)
  144. try:
  145. if headers[0][0].startswith("%PDF"):
  146. return True
  147. else:
  148. return False
  149. except IndexError:
  150. return False
  151. Binary.register_sniffable_binary_format("pdf", "pdf", Pdf)
  152. def create_applet_tag_peek( class_name, archive, params ):
  153. text = """
  154. <object classid="java:%s"
  155. type="application/x-java-applet"
  156. height="30" width="200" align="center" >
  157. <param name="archive" value="%s"/>""" % ( class_name, archive )
  158. for name, value in params.iteritems():
  159. text += """<param name="%s" value="%s"/>""" % ( name, value )
  160. text += """
  161. <object classid="clsid:8AD9C840-044E-11D1-B3E9-00805F499D93"
  162. height="30" width="200" >
  163. <param name="code" value="%s" />
  164. <param name="archive" value="%s"/>""" % ( class_name, archive )
  165. for name, value in params.iteritems():
  166. text += """<param name="%s" value="%s"/>""" % ( name, value )
  167. text += """<div class="errormessage">You must install and enable Java in your browser in order to access this applet.<div></object>
  168. </object>
  169. """
  170. return """<div><p align="center">%s</p></div>""" % text
  171. class Gmaj( data.Data ):
  172. """Class describing a GMAJ Applet"""
  173. file_ext = "gmaj.zip"
  174. copy_safe_peek = False
  175. def set_peek( self, dataset, is_multi_byte=False ):
  176. if not dataset.dataset.purged:
  177. if hasattr( dataset, 'history_id' ):
  178. params = {
  179. "bundle":"display?id=%s&tofile=yes&toext=.zip" % dataset.id,
  180. "buttonlabel": "Launch GMAJ",
  181. "nobutton": "false",
  182. "urlpause" :"100",
  183. "debug": "false",
  184. "posturl": "history_add_to?%s" % "&".join( map( lambda x: "%s=%s" % ( x[0], quote_plus( str( x[1] ) ) ), [ ( 'copy_access_from', dataset.id), ( 'history_id', dataset.history_id ), ( 'ext', 'maf' ), ( 'name', 'GMAJ Output on data %s' % dataset.hid ), ( 'info', 'Added by GMAJ' ), ( 'dbkey', dataset.dbkey ) ] ) )
  185. }
  186. class_name = "edu.psu.bx.gmaj.MajApplet.class"
  187. archive = "/static/gmaj/gmaj.jar"
  188. dataset.peek = create_applet_tag_peek( class_name, archive, params )
  189. dataset.blurb = 'GMAJ Multiple Alignment Viewer'
  190. else:
  191. dataset.peek = "After you add this item to your history, you will be able to launch the GMAJ applet."
  192. dataset.blurb = 'GMAJ Multiple Alignment Viewer'
  193. else:
  194. dataset.peek = 'file does not exist'
  195. dataset.blurb = 'file purged from disk'
  196. def display_peek(self, dataset):
  197. try:
  198. return dataset.peek
  199. except:
  200. return "peek unavailable"
  201. def get_mime(self):
  202. """Returns the mime type of the datatype"""
  203. return 'application/zip'
  204. def sniff(self, filename):
  205. """
  206. NOTE: the sniff.convert_newlines() call in the upload utility will keep Gmaj data types from being
  207. correctly sniffed, but the files can be uploaded (they'll be sniffed as 'txt'). This sniff function
  208. is here to provide an example of a sniffer for a zip file.
  209. """
  210. if not zipfile.is_zipfile( filename ):
  211. return False
  212. contains_gmaj_file = False
  213. zip_file = zipfile.ZipFile(filename, "r")
  214. for name in zip_file.namelist():
  215. if name.split(".")[1].strip().lower() == 'gmaj':
  216. contains_gmaj_file = True
  217. break
  218. zip_file.close()
  219. if not contains_gmaj_file:
  220. return False
  221. return True
  222. class Html( data.Text ):
  223. """Class describing an html file"""
  224. file_ext = "html"
  225. def set_peek( self, dataset, is_multi_byte=False ):
  226. if not dataset.dataset.purged:
  227. dataset.peek = "HTML file"
  228. dataset.blurb = data.nice_size( dataset.get_size() )
  229. else:
  230. dataset.peek = 'file does not exist'
  231. dataset.blurb = 'file purged from disk'
  232. def get_mime(self):
  233. """Returns the mime type of the datatype"""
  234. return 'text/html'
  235. def sniff( self, filename ):
  236. """
  237. Determines whether the file is in html format
  238. >>> fname = get_test_fname( 'complete.bed' )
  239. >>> Html().sniff( fname )
  240. False
  241. >>> fname = get_test_fname( 'file.html' )
  242. >>> Html().sniff( fname )
  243. True
  244. """
  245. headers = get_headers( filename, None )
  246. try:
  247. for i, hdr in enumerate(headers):
  248. if hdr and hdr[0].lower().find( '<html>' ) >=0:
  249. return True
  250. return False
  251. except:
  252. return True
  253. class Laj( data.Text ):
  254. """Class describing a LAJ Applet"""
  255. file_ext = "laj"
  256. copy_safe_peek = False
  257. def set_peek( self, dataset, is_multi_byte=False ):
  258. if not dataset.dataset.purged:
  259. if hasattr( dataset, 'history_id' ):
  260. params = {
  261. "alignfile1": "display?id=%s" % dataset.id,
  262. "buttonlabel": "Launch LAJ",
  263. "title": "LAJ in Galaxy",
  264. "posturl": quote_plus( "history_add_to?%s" % "&".join( [ "%s=%s" % ( key, value ) for key, value in { 'history_id': dataset.history_id, 'ext': 'lav', 'name': 'LAJ Output', 'info': 'Added by LAJ', 'dbkey': dataset.dbkey, 'copy_access_from': dataset.id }.items() ] ) ),
  265. "noseq": "true"
  266. }
  267. class_name = "edu.psu.cse.bio.laj.LajApplet.class"
  268. archive = "/static/laj/laj.jar"
  269. dataset.peek = create_applet_tag_peek( class_name, archive, params )
  270. else:
  271. dataset.peek = "After you add this item to your history, you will be able to launch the LAJ applet."
  272. dataset.blurb = 'LAJ Multiple Alignment Viewer'
  273. else:
  274. dataset.peek = 'file does not exist'
  275. dataset.blurb = 'file purged from disk'
  276. def display_peek(self, dataset):
  277. try:
  278. return dataset.peek
  279. except:
  280. return "peek unavailable"