1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218
|
# 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 __future__ import print_function
from Bio._py3k import basestring
from reportlab.lib import colors
class ColorTranslator(object):
""" 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, or a
ReportLab color object (returned as is).
(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")
elif isinstance(color, int):
color = self.scheme_color(color)
elif isinstance(color, colors.Color):
return color
elif isinstance(color, basestring):
# Assume its a named reportlab color like "red".
color = colors.toColor(color)
elif isinstance(color, tuple) and isinstance(color[0], float):
color = self.float1_color(color)
elif isinstance(color, tuple) and isinstance(color[0], int):
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
"""
with open(filename, 'r').readlines() as lines:
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 ValueError("Expected INT \t INT \t INT \t INT \t string input")
def get_artemis_colorscheme(self):
"""Return the Artemis color scheme as a dictionary."""
return self._artemis_colorscheme
def artemis_color(self, value):
"""Artemis color (integer) to ReportLab Color object.
Arguments:
- value: An int representing a functional class in the Artemis
color scheme (see www.sanger.ac.uk for a description),
or a string from a GenBank feature annotation for the
color which may be dot delimited (in which case the
first value is used).
Takes an int representing a functional class in the Artemis color
scheme, and returns the appropriate colors.Color object
"""
try:
value = int(value)
except ValueError:
if value.count('.'): # dot-delimited
value = int(value.split('.', 1)[0]) # Use only first integer
else:
raise
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):
"""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))
|