File: _Colors.py

package info (click to toggle)
python-biopython 1.68%2Bdfsg-3~bpo8%2B1
  • links: PTS, VCS
  • area: main
  • in suites: jessie-backports
  • size: 46,856 kB
  • sloc: python: 160,306; xml: 93,216; ansic: 9,118; sql: 1,208; makefile: 155; sh: 63
file content (218 lines) | stat: -rw-r--r-- 8,852 bytes parent folder | download | duplicates (2)
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))