text: # Copyright 2003-2008 by Leighton Pritchard.  All rights reserved.
  # This code is part of the Biopython distribution and governed by its
  # license.  Please see the LICENSE file that should have been included
  # as part of this package.
  #
  # Contact:       Leighton Pritchard, Scottish Crop Research Institute,
  #                Invergowrie, Dundee, Scotland, DD2 5DA, UK
  #                L.Pritchard@scri.ac.uk
  ################################################################################
  
  """ Colors module
  
      Provides:
  
      o ColorTranslator -  class to convert tuples of integers and floats into
                              colors.Color objects
  
      For drawing capabilities, this module uses reportlab to define colors:
  
      http://www.reportlab.com
  """
  
  # ReportLab imports
  from reportlab.lib import colors
  
  class ColorTranslator:
      """ Class providing methods for translating representations of color into
      """
      def __init__(self, filename=None):
          """ __init__(self, filename)
  
              o filename      Location of a file containing colorscheme
                              information
  
              Optional parameters set the color scheme 
          """
          self._artemis_colorscheme = {0: (colors.Color(1, 1, 1,), "pathogenicity, adaptation, chaperones"),
                 1: (colors.Color(0.39, 0.39, 0.39), "energy metabolism"),
                 2: (colors.Color(1, 0, 0), "information transfer"),
                 3: (colors.Color(0, 1, 0), "surface"),
                 4: (colors.Color(0, 0, 1), "stable RNA"),
                 5: (colors.Color(0, 1, 1), "degradation of large molecules"),
                 6: (colors.Color(1, 0, 1), "degradation of small molecules"),
                 7: (colors.Color(1, 1, 0), "central/intermediary/miscellaneous metabolism"),
                 8: (colors.Color(0.60, 0.98, 0.60), "unknown"),
                 9: (colors.Color(0.53, 0.81, 0.98), "regulators"),
                 10: (colors.Color(1, 0.65, 0), "conserved hypotheticals"),
                 11: (colors.Color(0.78, 0.59, 0.39), "pseudogenes and partial genes"),
                 12: (colors.Color(1, 0.78, 0.78), "phage/IS elements"),
                 13: (colors.Color(0.70, 0.70, 0.70), "some miscellaneous information"),
                 14: (colors.Color(0, 0, 0), ""),
                 15: (colors.Color(1, 0.25, 0.25), "secondary metabolism"),
                 16: (colors.Color(1, 0.5, 0.5), ""),
                 17: (colors.Color(1, 0.75, 0.75), "")
                  }      # Hardwired Artemis color scheme                                                                        
          self._colorscheme = {}
          if filename is not None:
              self.read_colorscheme(filename)# Imported color scheme
          else:
              self._colorscheme = self._artemis_colorscheme
  
  
      def translate(self, color=None, colour=None):
          """ translate(self, color)
  
              o color    Color defined as an int, a tuple of three ints 0->255
                         or a tuple of three floats 0 -> 1, or a string giving
                         one of the named colors defined by ReportLab.
  
                         (This argument is overridden by a backwards compatible
                         argument with UK spelling, colour).
  
              Returns a colors.Color object, determined semi-intelligently
              depending on the input values
          """
          #Let the UK spelling (colour) override the USA spelling (color)
          if colour is not None:
              color = colour
          
          if color is None:
              raise ValueError, "Passed color (or colour) must be a valid color type"
          if type(color) == type(1):
              color = self.scheme_color(color)
          elif isinstance(color, basestring):
              #Assume its a named reportlab color like "red".
              color = colors.toColor(color)
          elif type(color) == type((1., 2., 3.)) and type(color[0]) == type(1.):
              color = self.float1_color(color)        
          elif type(color) == type((1, 2, 3)) and type(color[0]) == type(1):
              color = self.int255_color(color)
          return color
          
  
      def read_colorscheme(self, filename):
          """ read_colorscheme(self, filename)
  
              o filename      The location of a file defining colors in tab-separated
                              format plaintext as:
                              INT \t RED \t GREEN \t BLUE \t Comment
                              Where RED, GREEN and BLUE are intensities in the range
                              0 -> 255
                              e.g.
                              2 \t 255 \t 0 \t 0 \t Red: Information transfer
  
              Reads information from a file containing color information and
              stores it internally
          """
          lines = open(filename, 'r').readlines()
          for line in lines:
              data = line.strip().split('\t')
              try:
                  label = int(data[0])
                  red, green, blue = int(data[1]), int(data[2]), int(data[3])
                  if len(data) > 4:
                      comment = data[4]
                  else:
                      comment = ""
                  self._colorscheme[label] = (self.int255_color((red, green, blue)),
                                               comment)
              except:
                  raise IOError, "Expected INT \t INT \t INT \t INT \t string input"
  
      def get_artemis_colorscheme(self):
          """ get_artemis_colorscheme(self)
  
              Return the Artemis color scheme as a dictionary
          """
          return self._artemis_colorscheme
          
  
      def artemis_color(self, value):
          """ artemis_color(self, value)
  
              o value     An int representing a functional class in the Artemis
                          color scheme (see www.sanger.ac.uk for a description)
  
              Takes an int representing a functional class in the Artemis color
              scheme, and returns the appropriate colors.Color object
          """
          value = int(value)
          if value in self._artemis_colorscheme:
              return self._artemis_colorscheme[value][0]
          else:
              raise ValueError, "Artemis color out of range: %d" % value
  
  
      def get_colorscheme(self):
          """ get_colorscheme(self)
  
              Return the user-defined color scheme as a dictionary
          """
          return self._colorscheme
  
  
      def scheme_color(self, value):
          """ scheme_color(self, value)
  
              o value     An int representing a single color in the user-defined
                          color scheme
  
              Takes an int representing a user-defined color and returns the
              appropriate colors.Color object
          """
          if value in self._colorscheme:
              return self._colorscheme[value][0]
          else:
              raise ValueError, "Scheme color out of range: %d" % value
  
  
      def int255_color(self, values):
          """ int255_color(self, values)
  
              o values        A tuple of (red, green, blue) intensities as
                              integers in the range 0->255
  
              Takes a tuple of (red, green, blue) intensity values in the range
              0 -> 255 and returns an appropriate colors.Color object
          """
          red, green, blue = values
          factor = 1/255.
          red, green, blue = red * factor, green * factor, blue * factor
          return colors.Color(red, green, blue)
  
  
      def float1_color(self, values):
          """ float1_color(self, values)
  
              o values        A tuple of (red, green, blue) intensities as floats
                              in the range 0 -> 1
  
              Takes a tuple of (red, green, blue) intensity values in the range
              0 -> 1 and returns an appropriate colors.Color object
          """
          red, green, blue = values
          return colors.Color(red, green, blue)
  
  
  ################################################################################
  # RUN AS SCRIPT
  ################################################################################
  
  if __name__ == '__main__':
  
      # Test code
      gdct = ColorTranslator()
      print gdct.float1_color((0.5, 0.5, 0.5))
      print gdct.int255_color((1, 75, 240))
      print gdct.artemis_color(7)
      print gdct.scheme_color(2)
  
      print gdct.translate((0.5, 0.5, 0.5))
      print gdct.translate((1, 75, 240))
      print gdct.translate(7)
      print gdct.translate(2)
  
                  
                          
  
  