Source code for admit.util.Image

""" .. _Image-api:

    **Image** --- Image data base.
    ------------------------------

    This module defines the Image class for IMAGE entries in BDPs as well as
    the imagedescriptor container class.
"""

# system imports
import xml.etree.cElementTree as et
import utils
import ast
import os

# ADMIT imports
import bdp_types as bt
from UtilBase import UtilBase


[docs]class Image(UtilBase): """ Defines the basic Image structure used in ADMIT. The class can store multiple types of the same image (e.g. png, jpg, CASA), however no check is made that they are the same image, this must be ensured by the AT using the class. A thumbnail, caption, and auxiliary file (for e.g. a histogram) are also included. Parameters ---------- keyvals : dictionary of new values for the keywords, optional. These keyword value pairs can be fed in form the command line instantiation of the class. Attributes ---------- images : dictionary Dictionary containing the image data, one entry per format type. thumbnail : string File name of the thumbnail image. thumbnailtype : string The format of the thumbnail, see bt for a list of available formats. auxiliary : string The name of the auxiliary file. auxtype : string The format of the auxiliary file, see bt for a list of available formats. description : string A description or caption for the image. """ def __init__(self, **keyval): self.images = {} # dictionary of images {Format:filename} self.thumbnail = "" # thumbnail of image self.thumbnailtype = "" # format of thumbnail self.auxiliary = "" # auxiliary file (typically a histogram) self.auxtype = "" # format of auxiliary file self.description = "" # image description/caption self.name = "" UtilBase.__init__(self, **keyval) def __str__(self): retstr = bt.format.BOLD + bt.color.GREEN + "Image :" + bt.format.END + os.linesep for i, j in self.__dict__.iteritems(): retstr = retstr + bt.format.BOLD + i + ": " + bt.format.END + str(j) + os.linesep return retstr
[docs] def serialize(self): """Create a string representation of the Image that can be converted to native Python structures with ast.literal_eval or back to a Table with deserialize(). Intended for the summary but can be used wherever. Parameters ---------- None Returns ------- A string representation of the Image that can be converted back to a Image with deserialize(). """ return str(self.__dict__)
[docs] def deserialize(self,serial): """Create an Image from serialized data created by serialize(). Parameters ---------- serial : The string representation of an Image in the format from deserialize(). Returns ------- None """ # Do not convert directly to self.__dict__ because # the Image structure may change between versions, e.g. # an attribute may be added or deleted. # So we can only safely convert attributes which are valid # for this Image instance. x = ast.literal_eval(serial) for i in self.__dict__: if i in x: self.__dict__[i] = x[i]
[docs] def setkey(self, name="", value=""): """ set keys, two styles are possible: 1. name = {key:val} e.g. **setkey({"a":1})** 2. name = "key", value = val e.g. **setkey("a", 1)** This method checks the type of the keyword value, as it must remain the same. Also new keywords cannot be added. Parameters ---------- name : dictionary or string Dictionary of keyword value pais to set or a string with the name of a single key value : any The value to change the keyword to Returns ------- None """ if isinstance(name, dict): for k, v in name.iteritems(): if k == "images" and isinstance(v, dict): for k1, v1 in v.iteritems(): if k1 == bt.THUMB or k1 == bt.AUX: raise Exception("Thumnails and auxiliary files cannot be added as part of the images item, they must be added under the thumbnail or auxiliary item.") if hasattr(self, k): if type(v) == type(getattr(self, k)): setattr(self, k, v) else: raise Exception("Cannot change data type for %s, expected %s but got %s" % (k, str(type(getattr(self, k))), str(type(v)))) else: raise Exception("Invalid key given to Image class: %s" % (k)) elif not name == "": if name == "images" and isinstance(value, dict): for k, v in value.iteritems(): if k == bt.THUMB or k == bt.AUX: raise Exception("Thumnails and auxiliary files cannot be added as part of the images item, they must be added under the thumbnail or auxiliary item.") if hasattr(self, name): if type(getattr(self, name)) == type(value): setattr(self, name, value) else: raise Exception("Cannot change data type for %s, expected %s but got %s" % (name, str(type(getattr(self, name))), str(type(value)))) else: raise Exception("Invalid key given to Image class: %s" % (name)) else: raise Exception("Invalid name parameter given, it must be a string or a dictionary of keys:values.")
[docs] def addimage(self, image): """ Method to add an image to the class Parameters ---------- image : List/ImageDescriptor Can be either a list of imagedescriptors or just an individual imagedescriptor. If the image type already exists in the class then it is replaced and the original removed. Any images labeled DATA will be added to the dictionary (overwriting any previous instances of the format) Returns ------- None """ if isinstance(image, list): for t in image: if(not t.format in bt.image_types): raise Exception("%s is not a valid image type, accepted types are: %s" % (t, str(bt.image_types))) if(not isinstance(t, imagedescriptor)) : raise Exception("Input image is not of imagedescriptor type or an imagedescriptor list") self.addfile(t) return elif(not isinstance(image, imagedescriptor)): raise Exception("Input image is not of imagedescriptor type or an imagedescriptor list") if(not image.type in bt.image_types + bt.imagedescriptor_types): raise Exception("%s is not a valid image type, accepted types are: %s" % (image.type, str(bt.image_types + bt.imagedescriptor_types))) self.addfile(image)
[docs] def addfile(self, image): """ Method to add a file to the class, it should not be called directly, instead addimage should be called Parameters ---------- image : ImageDescriptor An imagedescriptor of the image to be added. Removes any file that is being replaced Returns ------- None """ if(image.type == bt.DATA) : if(image.format in self.images): self.removeimage(image.format) self.images[image.format] = image.file elif(image.type == bt.THUMB): if(self.thumbnail is not None): self.removeimage(bt.THUMB) self.thumbnail = image.file self.thumbnailtype = image.format elif(image.type == bt.AUX): if(self.auxiliary is not None): self.removeimage(bt.AUX) self.auxiliary = image.file self.auxtype = image.format
[docs] def getimage(self, type): """ Method which returns the requested image from the class as an imagedescriptor. Parameters ---------- type : string Can be any of the following: bt.AUX to retrieve the auxiliary file, bt.THUMB to retrieve the thumbnail, or a file format (e.g. bt.FITS) to retrieve the requested format of the main image. If the requested image does not exist then None is returned. Returns ------- ImageDescriptor An imagedescriptor of the requested image or None if the image does not exist in the class. """ if(type == bt.AUX): if(self.auxiliary != ""): return imagedescriptor(self.auxiliary, self.auxtype, bt.AUX) return None if(type == bt.THUMB): if(self.thumbnail != ""): return imagedescriptor(self.thumbnail, self.thumbnailtype, bt.THUMB) return None try: if(type in self.images): return imagedescriptor(self.images[type], type, bt.DATA) except: print "NOT FOUND" return None return None
[docs] def getimagefile(self, imtype): """ Method to get the name of a file for the given image type Parameters ---------- imtype : str Can be any of the following: bt.AUX to retrieve the auxiliary file, bt.THUMB to retrieve the thumbnail, or a file format (e.g. bt.FITS) to retrieve the requested format of the main image. If the requested image does not exist then None is returned. Returns ------- String containing the image name, or None if the image does not exist """ temp = self.getimage(imtype) if temp is None: return None return temp.file
[docs] def removeimage(self, typ, basedir="", delete=True): """ Method to remove a specific image from the class, including from disk if requested. Parameters ---------- type : string The type of the image to be removed. Can be any of the following: bt.AUX to remove the auxiliary file, bt.THUMB to remove the thumbnail, or a file format (e.g. bt.FITS) to remove the requested format from the main image dictionary. delete : Boolean Whether to delete the actual image from disk (default is True) Returns ------- None """ # go through each image component and delete the file and instance if(typ == bt.THUMB): if(delete): utils.remove(basedir + os.sep + self.thumbnail) self.thumbnail = "" self.thumbnailtype = "" elif(typ == bt.AUX): if(delete): utils.remove(basedir + os.sep+ self.auxiliary) self.auxiliary = "" self.auxtype = "" elif(typ in bt.image_types and typ in self.images): if(delete): utils.remove(basedir + os.sep + self.images[typ]) elif(typ in self.images.values()): k = None for key, val in self.images.iteritems(): if(typ == val): k = key if(delete) : utils.remove(basedir + os.sep + k) self.images.pop(k, None) else: pass
[docs] def delete(self, basedir="", delfile=True): """ Method to delete everything Parameters ---------- delfile : Boolean Whether or not do delete the underlying files (default is True) Returns ------- None """ for f, v in self.images.iteritems(): self.removeimage(f, basedir, delfile) self.images = {} if(self.thumbnail != ""): self.removeimage(bt.THUMB, basedir, delfile) if(self.auxiliary != ""): self.removeimage(bt.AUX, basedir, delfile)
[docs] def getthumbnail(self): """ Method to get the thumbnail image file name Parameters ---------- None Returns ------- string The file name of the thumbnail image, relative to the encasing BDP """ return self.getimage(bt.THUMB)
[docs] def getaux(self): """ Method to get the auxiliary file name Returns ------- string The name of the auxiliry file, relative to the encasing BDP """ return self.getimage(bt.AUX)
def __eq__(self, img): """ Method to determine if two images are equivalent Parameters ---------- img : Image The image to compare to this one Returns ------- Boolean Whether or not the two image classes are equivalent Notes ----- Useful for testing purposes, still experimental """ try: for i in self.__dict__: if cmp(getattr(self, i), getattr(img, i)) != 0: return False except Exception, e: return False return True
[docs]class imagedescriptor(object): """ A lightweight class for transporting an image, its format and type. This class has three and only three data members, and no added methods. The members are file for the image file name on disk, format for the image format (e.g. bt.FITS), and type (one of bt.THUMB, bt.AUX, or bt.DATA) specifying what type of image this is. Parameters ---------- file : string The name of the file containing the image No default format : string The format the image is in (see bt for a list of formats) No default type : string The data type this image is filling in the class auxiliary, thumbnail or data (where most images go). Use: bt.AUX, bt.THUMB, or bt.DATA Default : bt.DATA) Attributes ---------- Same as parameters. """ __slots__ = ["file", "format", "type"] def __init__(self, file, format, type=bt.DATA) : if(not type in bt.imagedescriptor_types) : raise Exception("type %s is not a valid value. Valid values are %s" % (type, str(bt.imagedescriptor_types))) if(not format in bt.image_types): raise Exception("Format %s is not an acceptable format type" % (format)) self.file = file self.format = format self.type = type