This is an automated email from the git hooks/post-receive script. afif pushed a commit to branch master in repository python-colormap.
commit 131a179ca56d281eb879822382325d45ae98c8fe Author: Afif Elghraoui <[email protected]> Date: Tue Oct 17 23:43:46 2017 -0400 New upstream version 1.0.1 --- LICENSE | 28 + MANIFEST.in | 2 + PKG-INFO | 101 +++ README.rst | 74 +++ setup.cfg | 25 + setup.py | 71 +++ src/colormap.egg-info/PKG-INFO | 101 +++ src/colormap.egg-info/SOURCES.txt | 15 + src/colormap.egg-info/dependency_links.txt | 1 + src/colormap.egg-info/top_level.txt | 1 + src/colormap/__init__.py | 39 ++ src/colormap/colors.py | 990 +++++++++++++++++++++++++++++ src/colormap/get_cmap.py | 58 ++ src/colormap/xfree86.py | 173 +++++ test/test_colors.py | 246 +++++++ test/test_get_cmap.py | 16 + 16 files changed, 1941 insertions(+) diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..0d09cf4 --- /dev/null +++ b/LICENSE @@ -0,0 +1,28 @@ +Copyright (c) 2014, Thomas Cokelaer +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +* Neither the name of colormap nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + diff --git a/MANIFEST.in b/MANIFEST.in new file mode 100644 index 0000000..9d5d250 --- /dev/null +++ b/MANIFEST.in @@ -0,0 +1,2 @@ +include LICENSE +include README.rst diff --git a/PKG-INFO b/PKG-INFO new file mode 100644 index 0000000..d425aa6 --- /dev/null +++ b/PKG-INFO @@ -0,0 +1,101 @@ +Metadata-Version: 1.1 +Name: colormap +Version: 1.0.1 +Summary: Utilities to ease manipulation of matplotlib colormaps and color codecs (e.g., hex2rgb) +Home-page: ['http://packages.python.org/colormap/'] +Author: Thomas Cokelaer +Author-email: [email protected] +License: LGPL +Download-URL: ['http://pypi.python.org/pypi/colormap'] +Description: ############################# + COLORMAP documentation + ############################# + + + Please see : http://colormap.readthedocs.io/ for an up-to-date documentation. + + .. image:: https://badge.fury.io/py/colormap.svg + :target: https://pypi.python.org/pypi/colormap + + .. image:: https://secure.travis-ci.org/cokelaer/colormap.png + :target: http://travis-ci.org/cokelaer/colormap + + .. image:: https://coveralls.io/repos/cokelaer/colormap/badge.png?branch=master + :target: https://coveralls.io/r/cokelaer/colormap?branch=master + + .. image:: https://landscape.io/github/cokelaer/colormap/master/landscape.png + :target: https://landscape.io/github/cokelaer/colormap/master + + + :version: Python 2.7, 3.3, 3.4, 3.5, 3.6 + :contributions: Please join https://github.com/cokelaer/colormap + :issues: Please use https://github.com/cokelaer/colormap/issues + :notebook: Please see https://github.com/cokelaer/colormap/tree/master/notebooks + + + + What is it ? + ################ + + **colormap** package provides simple utilities to convert colors between + RGB, HEX, HLS, HUV and a class to easily build colormaps for matplotlib. All + matplotlib colormaps and some R colormaps are available altogether. The + plot_colormap method (see below) is handy to quickly pick up a colormaps and + the test_colormap is useful to see test a new colormap. + + + Installation + ################### + + :: + + pip install colormap + + Example + ########## + + * Create your own colormap from red to green colors with intermediate color as + whitish (diverging map from red to green):: + + c = Colormap() + mycmap = c.cmap( {'red':[1,1,0], 'green':[0,1,.39], 'blue':[0,1,0]}) + cmap = c.test_colormap(mycmap) + + * Even simpler if the colormap is linear:: + + c = Colormap() + mycmap = c.cmap_linear('red', 'black', 'green') + cmap = c.test_colormap(mycmap) + + .. image:: http://colormap.readthedocs.io/en/latest/_images/index-1.png + :width: 50% + :align: center + + * check out the available colormaps:: + + c = Colormap() + c.plot_colormap('diverging') + + .. image:: http://colormap.readthedocs.io/en/latest/_images/colormaps.png + :width: 50% + :align: center + + See online documentation for details: http://colormap.readthedocs.io/ + +Keywords: hex2web,web2hex,hex2rgb,rgb2hex,rgb2hsv,hsv2rgb,rgb2hls,hls2rgb,colormap,colors +Platform: Linux +Platform: Unix +Platform: MacOsX +Platform: Windows +Classifier: Development Status :: 5 - Production/Stable +Classifier: Intended Audience :: Developers +Classifier: Intended Audience :: Science/Research +Classifier: License :: OSI Approved :: GNU Library or Lesser General Public License (LGPL) +Classifier: Operating System :: OS Independent +Classifier: Programming Language :: Python :: 2.7 +Classifier: Programming Language :: Python :: 3.3 +Classifier: Programming Language :: Python :: 3.4 +Classifier: Programming Language :: Python :: 3.5 +Classifier: Topic :: Software Development :: Libraries :: Python Modules +Requires: matplotlib +Requires: easydev diff --git a/README.rst b/README.rst new file mode 100644 index 0000000..b95852b --- /dev/null +++ b/README.rst @@ -0,0 +1,74 @@ +############################# +COLORMAP documentation +############################# + + +Please see : http://colormap.readthedocs.io/ for an up-to-date documentation. + +.. image:: https://badge.fury.io/py/colormap.svg + :target: https://pypi.python.org/pypi/colormap + +.. image:: https://secure.travis-ci.org/cokelaer/colormap.png + :target: http://travis-ci.org/cokelaer/colormap + +.. image:: https://coveralls.io/repos/cokelaer/colormap/badge.png?branch=master + :target: https://coveralls.io/r/cokelaer/colormap?branch=master + +.. image:: https://landscape.io/github/cokelaer/colormap/master/landscape.png + :target: https://landscape.io/github/cokelaer/colormap/master + + +:version: Python 2.7, 3.3, 3.4, 3.5, 3.6 +:contributions: Please join https://github.com/cokelaer/colormap +:issues: Please use https://github.com/cokelaer/colormap/issues +:notebook: Please see https://github.com/cokelaer/colormap/tree/master/notebooks + + + +What is it ? +################ + +**colormap** package provides simple utilities to convert colors between +RGB, HEX, HLS, HUV and a class to easily build colormaps for matplotlib. All +matplotlib colormaps and some R colormaps are available altogether. The +plot_colormap method (see below) is handy to quickly pick up a colormaps and +the test_colormap is useful to see test a new colormap. + + +Installation +################### + +:: + + pip install colormap + +Example +########## + +* Create your own colormap from red to green colors with intermediate color as + whitish (diverging map from red to green):: + + c = Colormap() + mycmap = c.cmap( {'red':[1,1,0], 'green':[0,1,.39], 'blue':[0,1,0]}) + cmap = c.test_colormap(mycmap) + +* Even simpler if the colormap is linear:: + + c = Colormap() + mycmap = c.cmap_linear('red', 'black', 'green') + cmap = c.test_colormap(mycmap) + +.. image:: http://colormap.readthedocs.io/en/latest/_images/index-1.png + :width: 50% + :align: center + +* check out the available colormaps:: + + c = Colormap() + c.plot_colormap('diverging') + +.. image:: http://colormap.readthedocs.io/en/latest/_images/colormaps.png + :width: 50% + :align: center + +See online documentation for details: http://colormap.readthedocs.io/ diff --git a/setup.cfg b/setup.cfg new file mode 100644 index 0000000..d2c5ae0 --- /dev/null +++ b/setup.cfg @@ -0,0 +1,25 @@ +[sdist] + +[egg_info] +tag_build = +tag_date = 0 +tag_svn_revision = 0 + +[global] + +[build_sphinx] +source_dir = doc/source +build_dir = doc/build +all_files = 1 + +[nosetests] +where = test +with_coverage = True +cover_package = colormap +cover_erase = True +verbosity = 2 +logging_level = ERROR + +[upload_docs] +upload_dir = doc/build/html/ + diff --git a/setup.py b/setup.py new file mode 100644 index 0000000..2afad5a --- /dev/null +++ b/setup.py @@ -0,0 +1,71 @@ +# -*- coding: utf-8 -*- +__revision__ = "$Id: setup.py 3170 2013-01-16 14:57:19Z cokelaer $" +import sys +import os +from setuptools import setup, find_packages +import glob + +_MAJOR = 1 +_MINOR = 0 +_MICRO = 1 +version = '%d.%d.%d' % (_MAJOR, _MINOR, _MICRO) +release = '%d.%d' % (_MAJOR, _MINOR) + +metainfo = { + 'authors': {'Cokelaer':('Thomas Cokelaer','[email protected]')}, + 'version': version, + 'license' : 'LGPL', + 'download_url' : ['http://pypi.python.org/pypi/colormap'], + 'url' : ["http://packages.python.org/colormap/"], + 'description':'Utilities to ease manipulation of matplotlib colormaps and color codecs (e.g., hex2rgb)', + 'platforms' : ['Linux', 'Unix', 'MacOsX', 'Windows'], + 'keywords' : ["hex2web", "web2hex", "hex2rgb", "rgb2hex", "rgb2hsv", "hsv2rgb", + "rgb2hls", "hls2rgb", "colormap", 'colors'], + 'classifiers' : [ + 'Development Status :: 5 - Production/Stable', + 'Intended Audience :: Developers', + 'Intended Audience :: Science/Research', + 'License :: OSI Approved :: GNU Library or Lesser General Public License (LGPL)', + 'Operating System :: OS Independent', + 'Programming Language :: Python :: 2.7', + 'Programming Language :: Python :: 3.3', + 'Programming Language :: Python :: 3.4', + 'Programming Language :: Python :: 3.5', + 'Topic :: Software Development :: Libraries :: Python Modules' + ] + } + + +on_rtd = os.environ.get('READTHEDOCS', None) == 'True' +if on_rtd is True: # only import and set the theme if we're building docs + install_requires = ['matplotlib', 'easydev', "numpydoc"] +else: + install_requires = ['matplotlib', 'easydev'] + + + +setup( + name = 'colormap', + version = version, + maintainer = metainfo['authors']['Cokelaer'][0], + maintainer_email = metainfo['authors']['Cokelaer'][1], + author = metainfo['authors']['Cokelaer'][0], + author_email = metainfo['authors']['Cokelaer'][1], + long_description = open("README.rst").read(), + keywords = metainfo['keywords'], + description = metainfo['description'], + license = metainfo['license'], + platforms = metainfo['platforms'], + url = metainfo['url'], + download_url = metainfo['download_url'], + classifiers = metainfo['classifiers'], + + # package installation + package_dir = {'':'src'}, + packages = ['colormap'], + requires = install_requires, +) + + + + diff --git a/src/colormap.egg-info/PKG-INFO b/src/colormap.egg-info/PKG-INFO new file mode 100644 index 0000000..d425aa6 --- /dev/null +++ b/src/colormap.egg-info/PKG-INFO @@ -0,0 +1,101 @@ +Metadata-Version: 1.1 +Name: colormap +Version: 1.0.1 +Summary: Utilities to ease manipulation of matplotlib colormaps and color codecs (e.g., hex2rgb) +Home-page: ['http://packages.python.org/colormap/'] +Author: Thomas Cokelaer +Author-email: [email protected] +License: LGPL +Download-URL: ['http://pypi.python.org/pypi/colormap'] +Description: ############################# + COLORMAP documentation + ############################# + + + Please see : http://colormap.readthedocs.io/ for an up-to-date documentation. + + .. image:: https://badge.fury.io/py/colormap.svg + :target: https://pypi.python.org/pypi/colormap + + .. image:: https://secure.travis-ci.org/cokelaer/colormap.png + :target: http://travis-ci.org/cokelaer/colormap + + .. image:: https://coveralls.io/repos/cokelaer/colormap/badge.png?branch=master + :target: https://coveralls.io/r/cokelaer/colormap?branch=master + + .. image:: https://landscape.io/github/cokelaer/colormap/master/landscape.png + :target: https://landscape.io/github/cokelaer/colormap/master + + + :version: Python 2.7, 3.3, 3.4, 3.5, 3.6 + :contributions: Please join https://github.com/cokelaer/colormap + :issues: Please use https://github.com/cokelaer/colormap/issues + :notebook: Please see https://github.com/cokelaer/colormap/tree/master/notebooks + + + + What is it ? + ################ + + **colormap** package provides simple utilities to convert colors between + RGB, HEX, HLS, HUV and a class to easily build colormaps for matplotlib. All + matplotlib colormaps and some R colormaps are available altogether. The + plot_colormap method (see below) is handy to quickly pick up a colormaps and + the test_colormap is useful to see test a new colormap. + + + Installation + ################### + + :: + + pip install colormap + + Example + ########## + + * Create your own colormap from red to green colors with intermediate color as + whitish (diverging map from red to green):: + + c = Colormap() + mycmap = c.cmap( {'red':[1,1,0], 'green':[0,1,.39], 'blue':[0,1,0]}) + cmap = c.test_colormap(mycmap) + + * Even simpler if the colormap is linear:: + + c = Colormap() + mycmap = c.cmap_linear('red', 'black', 'green') + cmap = c.test_colormap(mycmap) + + .. image:: http://colormap.readthedocs.io/en/latest/_images/index-1.png + :width: 50% + :align: center + + * check out the available colormaps:: + + c = Colormap() + c.plot_colormap('diverging') + + .. image:: http://colormap.readthedocs.io/en/latest/_images/colormaps.png + :width: 50% + :align: center + + See online documentation for details: http://colormap.readthedocs.io/ + +Keywords: hex2web,web2hex,hex2rgb,rgb2hex,rgb2hsv,hsv2rgb,rgb2hls,hls2rgb,colormap,colors +Platform: Linux +Platform: Unix +Platform: MacOsX +Platform: Windows +Classifier: Development Status :: 5 - Production/Stable +Classifier: Intended Audience :: Developers +Classifier: Intended Audience :: Science/Research +Classifier: License :: OSI Approved :: GNU Library or Lesser General Public License (LGPL) +Classifier: Operating System :: OS Independent +Classifier: Programming Language :: Python :: 2.7 +Classifier: Programming Language :: Python :: 3.3 +Classifier: Programming Language :: Python :: 3.4 +Classifier: Programming Language :: Python :: 3.5 +Classifier: Topic :: Software Development :: Libraries :: Python Modules +Requires: matplotlib +Requires: easydev diff --git a/src/colormap.egg-info/SOURCES.txt b/src/colormap.egg-info/SOURCES.txt new file mode 100644 index 0000000..4bb5c7f --- /dev/null +++ b/src/colormap.egg-info/SOURCES.txt @@ -0,0 +1,15 @@ +LICENSE +MANIFEST.in +README.rst +setup.cfg +setup.py +src/colormap/__init__.py +src/colormap/colors.py +src/colormap/get_cmap.py +src/colormap/xfree86.py +src/colormap.egg-info/PKG-INFO +src/colormap.egg-info/SOURCES.txt +src/colormap.egg-info/dependency_links.txt +src/colormap.egg-info/top_level.txt +test/test_colors.py +test/test_get_cmap.py \ No newline at end of file diff --git a/src/colormap.egg-info/dependency_links.txt b/src/colormap.egg-info/dependency_links.txt new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/src/colormap.egg-info/dependency_links.txt @@ -0,0 +1 @@ + diff --git a/src/colormap.egg-info/top_level.txt b/src/colormap.egg-info/top_level.txt new file mode 100644 index 0000000..6cbac44 --- /dev/null +++ b/src/colormap.egg-info/top_level.txt @@ -0,0 +1 @@ +colormap diff --git a/src/colormap/__init__.py b/src/colormap/__init__.py new file mode 100644 index 0000000..0266932 --- /dev/null +++ b/src/colormap/__init__.py @@ -0,0 +1,39 @@ +# -*- python -*- +# -*- coding: utf-8 -*- +# +# This file is part of the colormap software +# +# Copyright (c) 2014 +# +# File author(s): Thomas Cokelaer <[email protected]> +# +# Distributed under the GPLv3 License. +# See accompanying file LICENSE.txt or copy at +# http://www.gnu.org/licenses/gpl-3.0.html +# +# Website: https://www.github.com/cokelaer/colormap +# Documentation: http://packages.python.org/colormap +# +############################################################################## +"""main colormap module""" +from __future__ import print_function +from __future__ import division + +import pkg_resources +try: + version = pkg_resources.require("colormap")[0].version + __version__ = version +except Exception: + version = '' + + +from .xfree86 import * +from . import colors +from .colors import * +from .get_cmap import * + +c = Colormap() +colormap_names = c.colormaps + c.diverging_black +# create an alias to test_colormap methiod +test_colormap = c.test_colormap +test_cmap = c.test_colormap diff --git a/src/colormap/colors.py b/src/colormap/colors.py new file mode 100644 index 0000000..b4c5cfc --- /dev/null +++ b/src/colormap/colors.py @@ -0,0 +1,990 @@ +# -*- python -*- +# -*- coding: utf-8 -*- +# +# This file is part of the colormap software +# +# Copyright (c) 2011-20134 +# +# File author(s): Thomas Cokelaer <[email protected]> +# +# Distributed under the GPLv3 License. +# See accompanying file LICENSE.txt or copy at +# http://www.gnu.org/licenses/gpl-3.0.html +# +# Website: https://github.com/cokelaer/colormap +# Documentation: http://packages.python.org/colormap +# +############################################################################## +"""Utilities provided in this module can be found either in the +standard Python module called :mod:`colorsys` or in matplotlib.colors +(e.g rgb2hex) or are original to this module (e.g., rgb2huv) + + +""" +# matplotlib dependence is only inside Colormap class +import colorsys +from easydev.tools import check_param_in_list, swapdict, check_range +from colormap.xfree86 import XFree86_colors + + +__all__ = ["HEX", "Color", "hex2web", "web2hex", "hex2rgb", "hex2dec", + "rgb2hex", "rgb2hsv", "hsv2rgb", "rgb2hls", "hls2rgb","yuv2rgb", "rgb2yuv", + "to_intensity", "yuv2rgb_int", "rgb2yuv_int", "Colormap" + ] + + +def hex2web(hexa): + """Convert hexadecimal string (6 digits) into *web* version (3 digits) + + .. doctest:: + + >>> from colormap.colors import hex2web + >>> hex2web("#FFAA11") + '#FA1' + + .. seealso:: :func:`web2hex`, :func:`hex2rgb` + :func:`rgb2hex`, :func:`rgb2hsv`, :func:`hsv2rgb`, :func:`rgb2hls`, + :func:`hls2rgb` + """ + hexa = HEX().get_standard_hex_color(hexa) + return "#" + hexa[1::2] + + +def web2hex(web): + """Convert *web* hexadecimal string (3 digits) into 6 digits version + + .. doctest:: + + >>> from colormap.colors import web2hex + >>> web2hex("#FA1") + '#FFAA11' + + .. seealso:: :func:`hex2web`, :func:`hex2rgb` + :func:`rgb2hex`, :func:`rgb2hsv`, :func:`hsv2rgb`, :func:`rgb2hls`, + :func:`hls2rgb` + """ + return HEX().get_standard_hex_color(web) + + +def hex2rgb(hexcolor, normalise=False): + """This function converts a hex color triplet into RGB + + Valid hex code are: + + * #FFF + * #0000FF + * 0x0000FF + * 0xFA1 + + + .. doctest:: + + >>> from colormap.colors import hex2rgb + >>> hex2rgb("#FFF", normalise=False) + (255, 255, 255) + >>> hex2rgb("#FFFFFF", normalise=True) + (1.0, 1.0, 1.0) + + + .. seealso:: :func:`hex2web`, :func:`web2hex`, + :func:`rgb2hex`, :func:`rgb2hsv`, :func:`hsv2rgb`, :func:`rgb2hls`, + :func:`hls2rgb` + """ + hexcolor = HEX().get_standard_hex_color(hexcolor)[1:] + r, g, b = int(hexcolor[0:2], 16), int(hexcolor[2:4], 16), int(hexcolor[4:6], 16) + if normalise: + r, g, b = _normalise(r, g, b) + return r, g, b + + +def rgb2hex(r, g, b, normalised=False): + """Convert RGB to hexadecimal color + + :param: can be a tuple/list/set of 3 values (R,G,B) + :return: a hex vesion ofthe RGB 3-tuple + + .. doctest:: + + >>> from colormap.colors import rgb2hex + >>> rgb2hex(0,0,255, normalised=False) + '#0000FF' + >>> rgb2hex(0,0,1, normalised=True) + '#0000FF' + + .. seealso:: :func:`hex2web`, :func:`web2hex`, :func:`hex2rgb` + , :func:`rgb2hsv`, :func:`hsv2rgb`, :func:`rgb2hls`, + :func:`hls2rgb` + + """ + if normalised: + r, g, b = _denormalise(r, g, b, mode="rgb") + r = int(r) + g = int(g) + b = int(b) + check_range(r, 0, 255) + check_range(g, 0, 255) + check_range(b, 0, 255) + return '#%02X%02X%02X' % (r, g, b) + + +def rgb2hls(r, g, b, normalised=True): + """Convert an RGB value to an HLS value. + + :param bool normalised: if *normalised* is True, the input RGB triplet + should be in the range 0-1 (0-255 otherwise) + :return: the HLS triplet. If *normalised* parameter is True, the output + triplet is in the range 0-1; otherwise, H in the range 0-360 and LS + in the range 0-100. + + .. doctest:: + + >>> from colormap.colors import rgb2hls + >>> rgb2hls(255,255,255, normalised=False) + (0.0, 1.0, 0.0) + + + .. seealso:: :func:`hex2web`, :func:`web2hex`, :func:`hex2rgb` + :func:`rgb2hex`, :func:`hsv2rgb`, + :func:`hls2rgb` + """ + # rgb_to_hsv expects normalised values ! + if normalised: + upper = 1 + else: + upper = 255 + check_range(r, 0, upper) + check_range(g, 0, upper) + check_range(b, 0, upper) + if normalised==False: + r, g, b = _normalise(r, g, b) + h, l, s = colorsys.rgb_to_hls(r, g, b) + return h, l, s + + +def rgb2hsv(r, g, b, normalised=True): + """Convert an RGB value to an HSV value. + + :param bool normalised: if *normalised* is True, the input RGB triplet + should be in the range 0-1 (0-255 otherwise) + :return: the HSV triplet. If *normalised* parameter is True, the output + triplet is in the range 0-1; otherwise, H in the range 0-360 and LS + in the range 0-100. + + .. doctest:: + + >>> from colormap.colors import rgb2hsv + >>> rgb2hsv(0.5,0,1) + (0.75, 1, 1) + + + .. seealso:: :func:`hex2web`, :func:`web2hex`, :func:`hex2rgb` + :func:`rgb2hex`, :func:`hsv2rgb`, :func:`rgb2hls`, + :func:`hls2rgb` + """ + # rgb_to_hsv expects normalised values ! + if normalised: + upper = 1 + else: + upper = 255 + check_range(r, 0, upper) + check_range(g, 0, upper) + check_range(b, 0, upper) + if normalised==False: + r, g, b = _normalise(r, g, b) + h, s, v = colorsys.rgb_to_hsv(r, g, b) + return h,s,v + + +def hsv2rgb(h, s, v, normalised=True): + """Convert a hue-saturation-value (HSV) value to a red-green-blue (RGB). + + :param bool normalised: If *normalised* is True, the input HSV triplet + should be in the range 0-1; otherwise, H in the range 0-360 and LS + in the range 0-100. + :return: the RGB triplet. The output + triplet is in the range 0-1 whether the input is normalised or not. + + .. doctest:: + + >>> from colormap.colors import hsv2rgb + >>> hsv2rgb(0.5,1,1, normalised=True) # doctest: +SKIP + (0, 1, 1) + + + .. seealso:: :func:`hex2web`, :func:`web2hex`, :func:`hex2rgb` + :func:`rgb2hex`, :func:`rgb2hsv`, :func:`rgb2hls`, + :func:`hls2rgb` + .. seealso:: :func:`rgb2hex` + """ + if normalised: + upper = 1 + else: + upper = 100 + if normalised: + uppera = 1 + else: + uppera = 360 + check_range(h, 0, uppera) + check_range(s, 0, upper) + check_range(v, 0, upper) + if normalised == False: + h, s, v = _normalise(h, s, v, mode="hsv") + return colorsys.hsv_to_rgb(h, s, v) + + +def hls2rgb(h, l, s, normalised=True): + """Convert an HLS value to a RGB value. + + :param bool normalised: If *normalised* is True, the input HLS triplet + should be in the range 0-1; otherwise, H in the range 0-360 and LS + in the range 0-100. + + :return: the RGB triplet. The output + triplet is in the range 0-1 whether the input is normalised or not. + + .. doctest:: + + >>> from colormap.colors import hls2rgb + >>> hls2rgb(360, 50, 60, normalised=False) # doctest: +SKIP + (0.8, 0.2, 0.2) + + + .. seealso:: :func:`hex2web`, :func:`web2hex`, :func:`hex2rgb` + :func:`rgb2hex`, :func:`rgb2hsv`, :func:`hsv2rgb`, :func:`rgb2hls`, + + """ + if normalised: + upper = 1 + else: + upper = 100 + if normalised: + uppera = 1 + else: + uppera = 360 + check_range(h, 0, uppera) + check_range(s, 0, upper) + check_range(l, 0, upper) + if normalised == False: + h, l, s = _normalise(h, l, s, mode="hls") + return colorsys.hls_to_rgb(h, l, s) + + +def hex2dec(data): + """convert integer (data) into hexadecimal.""" + return int(data, 16)/255. + + +def rgb2yuv(r, g, b): + """Convert RGB triplet into YUV + + :return: YUV triplet with values between 0 and 1 + + `YUV wikipedia <http://en.wikipedia.org/wiki/YUV>`_ + + .. warning:: expected input must be between 0 and 1 + .. note:: the constants referenc used is Rec. 601 + """ + check_range(r, 0, 1) + check_range(g, 0, 1) + check_range(b, 0, 1) + + #y = int(0.299 * r + 0.587 * g + 0.114 * b) + #u = int(-0.14713 * r + -0.28886 * g + 0.436 * b) + #v = int(0.615 * r + -0.51499 * g + -0.10001 * b) + + y = 0.299 * r + 0.587 * g + 0.114 * b + u = -32591.0/221500.0 * r + -63983.0/221500.0 * g + 0.436 * b + v = 0.615 * r + -72201./140200 * g + -7011/70100. * b + return (y, u, v) + + +def yuv2rgb(y, u, v): + """Convert YUV triplet into RGB + + `YUV <http://en.wikipedia.org/wiki/YUV>`_ + + .. warning:: expected input must be between 0 and 255 (not normalised) + + """ + check_range(y, 0,1) + check_range(u, 0, 1) + check_range(v, 0, 1) + A, B, C, D = 701.0/615.0, 25251.0/63983.0, 209599.0/361005.0, 443.0/218.0 + r = y + A * v + g = y - B * u - C * v + b = y + D * u + return (r, g, b) + + +def rgb2yuv_int(r, g, b): + """Convert RGB triplet into YUV + + `YUV wikipedia <http://en.wikipedia.org/wiki/YUV>`_ + + .. warning:: expected input must be between 0 and 255 (not normalised) + + """ + check_range(r, 0, 255) + check_range(g, 0, 255) + check_range(b, 0, 255) + + y = int(0.299 * r + 0.587 * g + 0.114 * b) + u = int(-32591.0/221500.0 * r + -63983.0/221500.0 * g + 0.436 * b) + v = int(0.615 * r + -72201./140200 * g + -7011/70100. * b) + + return (y, u, v) + + +def yuv2rgb_int(y, u, v): + """Convert YUV triplet into RGB + + `YUV <http://en.wikipedia.org/wiki/YUV>`_ + + .. warning:: expected input must be between 0 and 255 (not normalised) + + """ + check_range(y, 0, 255) + check_range(u, 0, 255) + check_range(v, 0, 255) + r = int(y + 1.13983 * v) + g = int(y - 0.39465 * u - 0.58060 * v) + b = int(y + 2.03211 * u) + return (r, g, b) + + +def _denormalise(r, g, b, mode="rgb"): + check_param_in_list(mode, ["rgb", "hls", "hsv"]) + if mode == "rgb": + return r*255., g*255., b*255. + elif mode in ["hls", "hsv"]: + return r*360., g*100., b*100. + + +def _normalise(r, g, b, mode="rgb"): + check_param_in_list(mode, ["rgb", "hls", "hsv"]) + if mode == "rgb": + return r/255., g/255., b/255. + elif mode in ["hls", "hsv"]: + return r/360., g/100., b/100. + + +def to_intensity(n): + """Return intensity + + :param n: value between 0 and 1 + :return: value between 0 and 255; round(n*127.5+127.5) + """ + check_range(n, 0, 1) + return int(round(n * 127.5 + 127.5)) + + +class HEX(object): + """Class to check the validity of an hexadecimal string and get standard string + + By standard, we mean #FFFFFF (6 digits) + + :: + + >>> h = HEX() + >>> h.is_valid_hex_color("#FFFF00") + True + + """ + def __init__(self): + pass + + def is_valid_hex_color(self, value, verbose=True): + """Return True is the string can be interpreted as hexadecimal color + + Valid formats are + + * #FFF + * #0000FF + * 0x0000FF + * 0xFA1 + """ + try: + self.get_standard_hex_color(value) + return True + except Exception as err: + if verbose: + print(err) + return False + + def get_standard_hex_color(self, value): + """Return standard hexadecimal color + + By standard, we mean a string that starts with # sign followed by 6 + character, e.g. #AABBFF + """ + if isinstance(value, str)==False: + raise TypeError("value must be a string") + if len(value) <= 3: + raise ValueError("input string must be of type 0xFFF, 0xFFFFFF or #FFF or #FFFFFF") + + if value.startswith("0x") or value.startswith("0X"): + value = value[2:] + elif value.startswith("#"): + value = value[1:] + else: + raise ValueError("hexa string must start with a '#' sign or '0x' string") + value = value.upper() + # Now, we have either FFFFFF or FFF + # now check the length + for x in value: + if x not in "0123456789ABCDEF": + raise ValueError("Found invalid hexa character {0}".format(x)) + + if len(value) == 6 or len(value) == 8: + value = "#" + value[0:6] + elif len(value) == 3: + value = "#" + value[0]*2 + value[1]*2 + value[2]*2 + else: + raise ValueError("hexa string should be 3, 6 or 8 digits. if 8 digits, last 2 are ignored") + return value + + +class Color(HEX): + """Class to ease manipulation and conversion between color codes + + You can create an instance in many differen ways. You can either use a + human-readable name as long as it is part of the + `XFree86 list <http://en.wikipedia.org/wiki/X11_color_names>`_ + You can also provide a hexadecimal string (either 3 or 6 digits). You can + use triplets of values corresponding to the RGB, HSV or HLS conventions. + + Here are some examples: + + .. doctest:: + + from colormap import Color + + Color("red") # human XFree86 compatible representation + Color("#f00") # standard 3 hex digits + Color("#ff0000") # standard 6 hex digits + Color(hsv=(0,1,0.5)) + Color(hls=(0, 1, 0.5)) # HLS triplet + Color(rgb=(1, 0, 0)) # RGB triplet + Color(Color("red")) # using an instance of :class:`Color` + + Note that the RGB, HLS and HSV triplets use normalised values. If you need + to normalise the triplet, you can use :mod:`colormap.colors._normalise` that + provides a function to normalise RGB, HLS and HSV triplets:: + + colors._normalise(*(255, 255, 0), mode="rgb") + colors._normalise(*(360, 50, 100), mode="hls") + + If you provide a string, it has to be a valid string from XFree86. + In addition to the official names, the lower case names are valid. Besides, + there are names with spaces. The equivalent names without space are also + valid. Therefore the name "Spring Green", which is an official name can be + provided as "Spring Green", "spring green", "springgreen" or "SpringGreen". + + """ + # Get official color names + colors = XFree86_colors.copy() + # add color names without spaces + aliases = dict([(x.replace(" ", ""),x) for x in colors.keys() if " " in x]) + # add color names without spaces in lower cases + aliases.update([(x.replace(" ", "").lower(),x) for x in colors.keys() if " " in x]) + # add color names in lower case + aliases.update(dict([(x.lower(),x) for x in colors.keys()])) + aliases.update(dict([(x,x) for x in colors.keys()])) + + # keep track of all possible names + color_names = sorted(list(set(list(colors.keys()) +list( aliases.keys())))) + + def __init__(self, name=None, rgb=None, hls=None, hsv=None): + super(Color, self).__init__() + self._name = None + self._mode = None + self._rgb = None + + # Does the user provided the name argument (first one) as a string ? + if isinstance(name, str): + # if so, it can be a valid human name (e.g., red) or an hex + # assuming that valid hexadecimal starts with # or 0x, + # if we can interpret the string as an hexadecimal, we are done + if self.is_valid_hex_color(name, verbose=False): + self.hex = name + else: + # if not, then, the user probably provided a valid color name + # the property will check the validity. + self.name = name[:] + #all other input parameters are ignored + elif name == None: + if rgb: + self.rgb = rgb + elif hls: + self.hls = hls + elif hsv: + self.hsv = hsv + else: + raise ValueError("You must set one of the parameter") + elif isinstance(name, Color): + self.rgb = name.rgb + else: + raise ValueError("name parameter must be a string") + + def _get_name(self): + return self._name + def _set_name(self, name): + check_param_in_list(name, self.color_names) + name = self.aliases[name] + self._name = name + # set hex and rgb at the same time based on the name + self.hex = self.colors[name] + name = property(_get_name, _set_name) + color = property(_get_name, _set_name) + + def _get_hex(self): + return self._hex + def _set_hex(self, value): + # hex is an approximation made of 255 bits so do not define rgb here + if self.is_valid_hex_color(value): + value = self.get_standard_hex_color(value) + self._hex = value + if self._hex in self.colors.values(): + self._name = swapdict(self.colors, check_ambiguity=False)[self._hex] + else: + self._name = "undefined" + self._rgb = hex2rgb(self._hex, normalise=True) + else: + # just to warn the user + self.get_standard_hex_color(value) + hex = property(_get_hex, _set_hex, + doc="getter/setter the hexadecimal value.") + + def _get_rgb(self): + return self._rgb + def _set_rgb(self, value): + # set name, hex and rgb + self.hex = rgb2hex(*value , normalised=True) + # must reset rgb with its real value (set_hex may round the rgb) + # in _set_hex + self._rgb = value + rgb = property(_get_rgb, _set_rgb, + doc="getter/setter the RGB values (3-length tuple)") + + def _get_hsv(self): + hsv = rgb2hsv(*self.rgb) + return hsv + def _set_hsv(self, value): + # TODO: value must be normalised + self.rgb = hsv2rgb(*value) + hsv = property(_get_hsv, _set_hsv, + doc="getter/setter the HSV values (3-length tuple)") + + def _get_hls(self): + hls = rgb2hls(*self.rgb) + return hls + def _set_hls(self, value): + #hls = _normalise(*value, mode="hls") + #else: + hls = value + self.rgb = hls2rgb(*hls) + hls = property(_get_hls, _set_hls, + doc="getter/setter the HLS values (3-length tuple)") + + def _get_lightness(self): + return self.hls[1] + def _set_lightness(self, lightness): + h, l, s = self.hls + self.hls = (h, lightness, s) + lightness = property(_get_lightness, _set_lightness, + doc="getter/setter the lightness in the HLS triplet") + + def _get_saturation_hls(self): + return self.hls[2] + def _set_saturation_hls(self, saturation): + h, l, s = self.hls + self.hls = (h, l, saturation) + saturation_hls = property(_get_saturation_hls, _set_saturation_hls, + doc="getter/setter the saturation in the HLS triplet") + + def _get_hue(self): + return self.hls[0] + def _set_hue(self, hue): + h, l, s = self.hls + self.hls = (hue, l, s) + hue = property(_get_hue, _set_hue, + doc="getter/setter the saturation in the HLS triplet") + + def _get_red(self): + return self.rgb[0] + def _set_red(self, red): + r, g, b = self.rgb + self.rgb = (red,g,b) + red = property(_get_red, _set_red, + doc="getter/setter for the red color in RGB triplet") + + def _get_green(self): + return self.rgb[1] + def _set_green(self, green): + r, g, b = self.rgb + self.rgb = (r, green, b) + green = property(_get_green, _set_green, + doc="getter/setter for the green color in RGB triplet") + + def _get_blue(self): + return self.rgb[2] + def _set_blue(self, blue): + r, g, b = self.rgb + self.rgb = (r, g, blue) + blue = property(_get_blue, _set_blue, + doc="getter/setter for the blue color in RGB triplet") + + def _get_value(self): + return self.hls[0] + def _set_value(self, value): + h, s, v = self.hsv + self.hsv = (h, s, value) + value = property(_get_value, _set_value, + doc="getter/setter the value in the HSV triplet") + + def _get_yiq(self): + return colorsys.rgb_to_yiq(*self.rgb) + yiq = property(_get_yiq, doc="Getter for the YIQ triplet") + + def __str__(self): + txt = 'Color {0}\n'.format(self.name) + txt+= ' hexa code: {0}\n'.format(self.hex) + txt+= ' RGB code: {0}\n'.format(self.rgb) + txt+= ' RGB code (un-normalised): {0}\n\n'.format([x*255 for x in self.rgb]) + txt+= ' HSV code: {0}\n'.format(self.hsv) + txt+= ' HSV code: (un-normalised) {0} {1} {2}\n\n'.format(self.hsv[0]*360, self.hsv[1]*100, self.hsv[2]*100) + txt+= ' HLS code: {0}\n'.format(self.hls) + txt+= ' HLS code: (un-normalised) {0} {1} {2}\n\n'.format(self.hls[0]*360, self.hls[1]*100, self.hls[2]*100) + return txt + + +class Colormap(object): + """Class to create matplotlib colormap + + This example show how to get the pre-defined colormap called *heat* + + .. plot:: + :include-source: + + + from pylab import * + from colormap.colors import Colormap + + c = Colormap() + cmap = c.get_cmap_heat() + c.test_colormap(cmap) + + You may be more interested in building your own colormap:: + + # design your own colormap + d = {'blue': [0,0,0,1,1,1,0], + 'green':[0,1,1,1,0,0,0], + 'red': [1,1,0,0,0,1,1]} + cmap = c.cmap(d, reverse=False) + + # see the results + c.test_colormap(cmap) + + If you want a simple linear colormap, you can use the example above, + or use the :meth:`cmap_linear`. For instance for a diverging colormap + from red to green (with with color in between):: + + cmap = c.cmap_linear("red", "white", "green") + c.test_colormap(cmap) + + Even simpler, you can use a bicolor colormap :meth:`cmap_bicolor`. For instance + for a red to green colormap:: + + cmap = c.cmap_bicolor("red", "green") + c.test_colormap(cmap) + + From matplotlib documentation, colormaps falls into 4 categories: + + #. Sequential schemes for unipolar data that progresses from low to high + #. Diverging schemes for bipolar data that emphasizes positive or + negative deviations from acentral value + #. Cyclic schemes meant for plotting values that wrap around at the + endpoints, such as phase angle, wind direction, or time of day + #. Qualitative schemes for nominal data that has no inherent ordering, + where color is used only to distinguish categories + + + :references: matplotlib documentation and examples + http://matplotlib.org/examples/color/colormaps_reference.html + """ + def _get_colormap_mpl(self): + try: + from matplotlib.pyplot import colormaps as _cmaps + return _cmaps() + except: + return [] + colormaps = property(_get_colormap_mpl) + + def _get_sequentials(self): + return ['Blues', 'BuGn', 'BuPu', 'GnBu', 'Greens', 'Greys', 'OrRd', + 'Oranges', 'PuBu', 'PuBuGn', 'PuRd', 'Purples', 'RdPu', + 'Reds', 'YlGn', 'YlGnBu', 'YlOrBr', 'YlOrRd'] + sequentials = property(_get_sequentials) + + def _get_sequentials2(self): + return ['afmhot', 'autumn', 'bone', 'cool', 'copper', + 'gist_heat', 'gray', 'hot', 'pink', + 'spring', 'summer', 'winter'] + sequentials2 = property(_get_sequentials2) + + def _get_diverging(self): + return ['BrBG', 'PRGn', 'PiYG', 'PuOr', 'RdBu', 'RdGy', 'RdYlBu', + 'RdYlGn', 'Spectral', 'bwr', 'coolwarm', 'seismic'] + diverging = property(_get_diverging) + + def _get_diverging_black(self): + return ['red_black_sky', 'red_black_blue', 'red_black_green', 'yellow_black_blue', + 'yellow_black_sky', 'red_black_orange', 'pink_black_green(w3c)' + ] + diverging_black = property(_get_diverging_black) + + def _get_qualitative(self): + return ['Accent', 'Dark2', 'Paired', 'Pastel1', 'Pastel2', + 'Set1', 'Set2', 'Set3'] + qualitative = property(_get_qualitative) + + def _get_misc(self): + return ['gist_earth', 'terrain', 'ocean', 'gist_stern', + 'brg', 'CMRmap', 'cubehelix', 'gnuplot', 'gnuplot2', 'gist_ncar', + 'nipy_spectral', 'jet', 'rainbow', 'gist_rainbow', 'hsv', 'flag', 'prism'] + misc = property(_get_misc) + + def plot_rgb_from_hex_list(self, cols): + """This functions takes a list of hexadecimal values and plots + the RGB curves. This can be handy to figure out the RGB functions + to be used in the :meth:`get_cmap`. + + .. plot:: + :include-source: + :width: 60% + + from colormap.colors import Colormap + c = Colormap() + t = ['#FF0000FF', '#FF4D00FF', '#FF9900FF', '#FFE500FF', + '#CCFF00FF', '#80FF00FF', '#33FF00FF', '#00FF19FF', + '#00FF66FF', '#00FFB2FF', '#00FFFFFF', '#00B3FFFF', + '#0066FFFF', '#001AFFFF', '#3300FFFF', '#7F00FFFF', + '#CC00FFFF','#FF00E6FF','#FF0099FF', '#FF004DFF'] + c.plot_rgb_from_hex_list(t) + + """ + import pylab + red = [hex2rgb(x)[0]/255. for x in cols] + blue = [hex2rgb(x)[2]/255. for x in cols] + green = [hex2rgb(x)[1]/255. for x in cols] + x = pylab.linspace(0, 1, len(cols)) + pylab.clf() + pylab.plot(x, red, 'ro-', alpha=0.5) + pylab.plot(x, green, 'gs-', alpha=0.5, markersize=15) + pylab.plot(x, blue, 'bx-', alpha=0.5, markersize=15) + pylab.ylim([-0.1, 1.1]) + + def cmap_bicolor(self, color1, color2, reverse=False, N=256): + """Provide 3 colors in format accepted by :class:`Color` + + :: + + >>> red = Color('red') + >>> white = Color('white') + >>> cmap = cmap_bicolor(red, white) + + """ + c1 = Color(color1) + c2 = Color(color2) + dico = {'red': [c1.red, c2.red], + 'green':[c1.green, c2.green], + 'blue':[c1.blue, c2.blue]} + return self.cmap(dico, reverse=reverse, N=N) + + def cmap_linear(self, color1, color2, color3, reverse=False, N=256): + """Provide 3 colors in format accepted by :class:`Color` + + :: + + red = Color('red') + cmap = cmap_linear(red, 'white', '#0000FF') + + """ + c1 = Color(color1) + c2 = Color(color2) + c3 = Color(color3) + dico = {'red': [c1.red, c2.red, c3.red], + 'green':[c1.green, c2.green, c3.green], + 'blue':[c1.blue, c2.blue, c3.blue]} + + return self.cmap(dico, reverse=reverse, N=N) + + def cmap(self, colors=None, reverse=False, N=256): + """Return a colormap object to be used within matplotlib + + :param dict colors: a dictionary that defines the RGB colors to be + used in the colormap. See :meth:`get_cmap_heat` for an example. + :param bool reverse: reverse the colormap is set to True (defaults to False) + :param int N: Defaults to 50 + + """ + # matplotlib colormaps + if colors in self.colormaps: + if reverse and colors.endswith("_r") is False: + colors += "_r" + from matplotlib.cm import get_cmap + return get_cmap(colors) + # custom ones + elif colors in self.diverging_black: + c1, c2, c3 = colors.split("_") + # special case of sky, which does not exists + c3 = c3.replace("sky", "deep sky blue") + return self.cmap_linear(c1, c2, c3) + elif colors == 'heat': + return self.get_cmap_heat() + elif colors == 'heat_r': + return self.get_cmap_heat_r() + + + # Keep these dependencies inside the function to allow + # installation of colormap without those dependencies + # FIXME remove numpy dependencies + import numpy as np + # extracted from R, heat.colors(20) + + if reverse: + for k in colors.keys(): + colors[k].reverse() + + # If index not given, RGB colors are evenly-spaced in colormap. + index = np.linspace(0, 1, len(colors['red'])) + + # Adapt color_data to the form expected by LinearSegmentedColormap. + color_data = dict((key, [(x, y, y) for x, y in zip(index, value)]) + for key, value in list(colors.items())) + + import matplotlib + f = matplotlib.colors.LinearSegmentedColormap + m = f('my_color_map', color_data, N) + return m + + + def get_cmap_heat(self): + """Return a heat colormap matplotlib-compatible colormap + + This heat colormap should be equivalent to heat.colors() in R. + + :: + + >>> from colormap.colors import Colormap + >>> cmap = Colormap.get_cmap_heat() + + You can generate the colormap based solely on this information for the RGB + functions along:: + + d= { 'blue':[0,0,0,0,1], + 'green':[0,.35,.7,1,1], + 'red':[1,1,1,1,1]} + cmap = Colormap.get_cmap(d) + + """ + return self.cmap( + { 'blue':[0, 0, 0, 0, 1], + 'green':[0, .35, .7, 1, 1], + 'red':[1, 1, 1, 1, 1]}, reverse=False) + + def get_cmap_heat_r(self): + """Return a heat colormap matplotlib-compatible colormap + + Same as :meth:`get_cmap_heat` but reversed + """ + return self.cmap( + { 'blue':[0, 0, 0, 0, 1], + 'green':[0, .35, .7, 1, 1], + 'red':[1, 1, 1, 1, 1]}, reverse=True) + + def get_cmap_rainbow(self): + """colormap similar to rainbow colormap from R + + .. note:: The red is actually appearing on both sides... Yet + this looks like what is coded in R 3.0.1 + + """ + return self.cmap( + { 'blue': [0, 0, 0, 1, 1, 1, 0], + 'green':[0, 1, 1, 1, 0, 0, 0], + 'red': [1, 1, 0, 0, 0, 1, 1]}, reverse=False) + + + def get_cmap_red_green(self): + return self.cmap( + { 'green': [0, 0.4, 0.6, .75, .8, .9, 1, .9, .8, .6], + 'blue' : [0, .4, .6, .75, .8, .7, .6, .35, .17, .1], + 'red': [1, 1, 1, 1, 1, .9, .8, .6, .3, .1]}, reverse=True) + + def test_colormap(self, cmap=None): + """plot one colormap for testing + + By default, test the :meth:`get_cmap_heat` + + """ + if cmap is None: + cmap = self.get_cmap_heat() + import numpy as np + from pylab import clf, pcolor, colorbar, show, linspace, axis + A, B = np.meshgrid(linspace(0, 10, 100), linspace(0, 10, 100)) + clf() + pcolor((A-5)**2+(B-5)**2, cmap=cmap) + colorbar() + show() + axis('off') + + def plot_colormap(self, cmap_list=None): + """cmap_list list of valid cmap or name of a set (sequential, + diverging,) + + if none, plot all known colors + + .. .. plot:: + .. :width:80% + .. :include-source: + + .. from colormap import Colormap + .. c = Colormap() + .. c.plot_colormap('sequential') + + + """ + from pylab import subplots + + if isinstance(cmap_list, str): + if cmap_list in ['sequentials','sequentials2','qualitative', + 'misc','diverging', 'diverging_black']: + cmap_list = getattr(self, cmap_list) + else: + cmap_list = [cmap_list] + if isinstance(cmap_list, list) is not True: + raise TypeError("""input must be a list of srtings or a single string. Each string should be found. For a user-defined cmap, use test_colormap""") + for this in cmap_list: + if this not in self.colormaps and this not in self.diverging_black: + raise ValueError("unknown colormap name. Please check valid names in colormaps attribute") + + nrows = len(cmap_list) + + gradient = [x/255. for x in range(0,256)] + gradient = [gradient, gradient] + #np.vstack((gradient, gradient)) + + fig, axes = subplots(nrows=nrows) + fig.subplots_adjust(top=0.95, bottom=0.05, left=0.05, right=0.8) + + for ax, name in zip(axes, cmap_list): + ax.imshow(gradient, aspect='auto', cmap=self.cmap(name)) + pos = list(ax.get_position().bounds) + x_text = pos[2] + 0.08 + y_text = pos[1] + pos[3]/2. + fig.text(x_text, y_text, name, va='center', ha='left', fontsize=10) + + # Turn off *all* ticks & spines, not just the ones with colormaps. + for ax in axes: + ax.set_axis_off() diff --git a/src/colormap/get_cmap.py b/src/colormap/get_cmap.py new file mode 100644 index 0000000..0c1e4bf --- /dev/null +++ b/src/colormap/get_cmap.py @@ -0,0 +1,58 @@ +# -*- python -*- +# +# This file is part of colormap software +# +# Copyright (c) 2014L +# +# File author(s): Thomas Cokelaer <[email protected]> +# +# Distributed under the GPLv3 License. +# See accompanying file LICENSE.txt or copy at +# http://www.gnu.org/licenses/gpl-3.0.html +# +# website: +# +############################################################################## +from colormap import Colormap + +__all__ = ['cmap_builder'] + + +def cmap_builder(name, name2=None, name3=None): + """return a colormap object compatible with matplotlib + + If only parameter **name** is provided, it should be a known matplotlib + colormap name (e.g., jet). If **name2** is provided, then a new colormap + is created going from the color **name** to the color **name2** with a + linear scale. Finally, if **name3** is provided, a linear scaled colormap + is built from color **name** to color **name3** with the intermediate color + being the **name2** + + Matplotlib colormap map names + + """ + c = Colormap() + # an R colormap + if name and name2 and name3: + return c.cmap_linear(name, name2, name3) + elif name and name2: + return c.cmap_bicolor(name, name2) + elif name == 'heat': + return c.get_cmap_heat() + elif name == 'heat_r': + return c.get_cmap_heat_r() + # matplotlic colormaps + elif name in c.colormaps: + return c.cmap(name) + # some custom diverging colormaps with black in the middle. + elif name in c.diverging_black: + return c.cmap(name) + elif name.count("_") == 2: + name1, name2, name3 = name.split("_") + return c.cmap_linear(name1, name2, name3) + else: + #valid = c.colormaps + c.diverging_black + txt = "name provided {0} is not recognised. ".format(name) + txt += "\n valid name can be found in colormap.colormap_names" + raise ValueError(txt) + diff --git a/src/colormap/xfree86.py b/src/colormap/xfree86.py new file mode 100644 index 0000000..d8d3238 --- /dev/null +++ b/src/colormap/xfree86.py @@ -0,0 +1,173 @@ +# -*- python -*- +# -*- coding: utf-8 -*- +# +# This file is part of the colormap software +# +# Copyright (c) 2014 +# +# File author(s): Thomas Cokelaer <[email protected]> +# +# Distributed under the GPLv3 License. +# See accompanying file LICENSE.txt or copy at +# http://www.gnu.org/licenses/gpl-3.0.html +# +# Website: https://www.github.com/cokelaer/colormap +# Documentation: http://packages.python.org/colormap +# +############################################################################## + +__all__ = ["XFree86_colors"] + +# TC: I have added the "green" key, which is the same as green(x11) + +XFree86_colors = { + "Alice Blue" : "#F0F8FF", + "AliceBlue" : "#F0F8FF", + "Antique White" : "#FAEBD7", + "Aqua" : "#00FFFF", + "Aquamarine" : "#7FFFD4", + "Azure" : "#F0FFFF", + "Beige" : "#F5F5DC", + "Bisque" : "#FFE4C4", + "Black" : "#000000", + "Blanched Almond" : "#FFEBCD", + "Blue" : "#0000FF", + "Blue Violet" : "#8A2BE2", + "Brown" : "#A52A2A", + "Burlywood" : "#DEB887", + "Cadet Blue" : "#5F9EA0", + "Chartreuse" : "#7FFF00", + "Chocolate" : "#D2691E", + "Coral" : "#FF7F50", + "Cornflower" : "#6495ED", + "Cornsilk" : "#FFF8DC", + "Crimson" : "#DC143C", + "Cyan" : "#00FFFF", + "Dark Blue" : "#00008B", + "Dark Cyan" : "#008B8B", + "Dark Goldenrod" : "#B8860B", + "Dark Gray" : "#A9A9A9", + "Dark Green" : "#006400", + "Dark Khaki" : "#BDB76B", + "Dark Magenta" : "#8B008B", + "Dark Olive Green" : "#556B2F", + "Dark Orange" : "#FF8C00", + "Dark Orchid" : "#9932CC", + "Dark Red" : "#8B0000", + "Dark Salmon" : "#E9967A", + "Dark Sea Green" : "#8FBC8F", + "Dark Slate Blue" : "#483D8B", + "Dark Slate Gray" : "#2F4F4F", + "Dark Turquoise" : "#00CED1", + "Dark Violet" : "#9400D3", + "Deep Pink" : "#FF1493", + "Deep Sky Blue" : "#00BFFF", + "Dim Gray" : "#696969", + "Dodger Blue" : "#1E90FF", + "Firebrick" : "#B22222", + "Floral White" : "#FFFAF0", + "Forest Green" : "#228B22", + "Fuchsia" : "#FF00FF", + "Gainsboro" : "#DCDCDC", + "Ghost White" : "#F8F8FF", + "Gold" : "#FFD700", + "Goldenrod" : "#DAA520", + "Gray (X11)" : "#BEBEBE", + "Gray (W3C)" : "#808080", + "Green (X11)" : "#00FF00", + "Green" : "#00FF00", + "Green (W3C)" : "#008000", + "Green Yellow" : "#ADFF2F", + "Honeydew" : "#F0FFF0", + "Hot Pink" : "#FF69B4", + "Indian Red" : "#CD5C5C", + "Indigo" : "#4B0082", + "Ivory" : "#FFFFF0", + "Khaki" : "#F0E68C", + "Lavender" : "#E6E6FA", + "Lavender Blush" : "#FFF0F5", + "Lawn Green" : "#7CFC00", + "Lemon Chiffon" : "#FFFACD", + "Light Blue" : "#ADD8E6", + "Light Coral" : "#F08080", + "Light Cyan" : "#E0FFFF", + "Light Goldenrod" : "#FAFAD2", + "Light Gray" : "#D3D3D3", + "Light Green" : "#90EE90", + "Light Pink" : "#FFB6C1", + "Light Salmon" : "#FFA07A", + "Light Sea Green" : "#20B2AA", + "Light Sky Blue" : "#87CEFA", + "Light Slate Gray" : "#778899", + "Light Steel Blue" : "#B0C4DE", + "Light Yellow" : "#FFFFE0", + "Lime (W3C)" : "#00FF00", + "Lime Green" : "#32CD32", + "Linen" : "#FAF0E6", + "Magenta" : "#FF00FF", + "Maroon (X11)" : "#B03060", + "Maroon (W3C)" : "#7F0000", + "Medium Aquamarine" : "#66CDAA", + "Medium Blue" : "#0000CD", + "Medium Orchid" : "#BA55D3", + "Medium Purple" : "#9370DB", + "Medium Sea Green" : "#3CB371", + "Medium Slate Blue" : "#7B68EE", + "Medium Spring Green" : "#00FA9A", + "Medium Turquoise" : "#48D1CC", + "Medium Violet Red" : "#C71585", + "Midnight Blue" : "#191970", + "Mint Cream" : "#F5FFFA", + "Misty Rose" : "#FFE4E1", + "Moccasin" : "#FFE4B5", + "Navajo White" : "#FFDEAD", + "Navy" : "#000080", + "Old Lace" : "#FDF5E6", + "Olive" : "#808000", + "Olive Drab" : "#6B8E23", + "Orange" : "#FFA500", + "Orange Red" : "#FF4500", + "Orchid" : "#DA70D6", + "Pale Goldenrod" : "#EEE8AA", + "Pale Green" : "#98FB98", + "Pale Turquoise" : "#AFEEEE", + "Pale Violet Red" : "#DB7093", + "Papaya Whip" : "#FFEFD5", + "Peach Puff" : "#FFDAB9", + "Peru" : "#CD853F", + "Pink" : "#FFC0CB", + "Plum" : "#DDA0DD", + "Powder Blue" : "#B0E0E6", + "Purple (X11)" : "#A020F0", + "Purple (W3C)" : "#7F007F", + "Red" : "#FF0000", + "Rosy Brown" : "#BC8F8F", + "Royal Blue" : "#4169E1", + "Saddle Brown" : "#8B4513", + "Salmon" : "#FA8072", + "Sandy Brown" : "#F4A460", + "Sea Green" : "#2E8B57", + "Seashell" : "#FFF5EE", + "Sienna" : "#A0522D", + "Silver (W3C)" : "#C0C0C0", + "Sky Blue" : "#87CEEB", + "Slate Blue" : "#6A5ACD", + "Slate Gray" : "#708090", + "Snow" : "#FFFAFA", + "Spring Green" : "#00FF7F", + "Steel Blue" : "#4682B4", + "Tan" : "#D2B48C", + "Teal" : "#008080", + "Thistle" : "#D8BFD8", + "Tomato" : "#FF6347", + "Turquoise" : "#40E0D0", + "Violet" : "#EE82EE", + "Wheat" : "#F5DEB3", + "White" : "#FFFFFF", + "White Smoke" : "#F5F5F5", + "Yellow" : "#FFFF00", + "Yellow Green" : "#9ACD32"} + + + + diff --git a/test/test_colors.py b/test/test_colors.py new file mode 100644 index 0000000..3ae015f --- /dev/null +++ b/test/test_colors.py @@ -0,0 +1,246 @@ +from colormap import colors +from colormap.colors import * +from easydev.easytest import assert_list_almost_equal + + +def test_hex2web(): + assert hex2web("#FFAA11") == "#FA1" + +def test_web2hex(): + assert web2hex("#FA1") == "#FFAA11" + +def test_rgb2yuv(): + assert_list_almost_equal(rgb2yuv(1,1,1) , (1,0,0)) + assert_list_almost_equal(rgb2yuv_int(255,255,255) , (255,0,0)) + + assert_list_almost_equal(yuv2rgb(1,0,0) , (1,1,1)) + assert_list_almost_equal(yuv2rgb_int(255,0,0) , (255,255,255)) + + +def test_rgb2hsv(): + assert_list_almost_equal( colors.rgb2hsv(0,1,1) , (0.5,1,1)) + assert_list_almost_equal(colors.rgb2hsv(0,255,255, normalised=False) , (0.5,1,1)) + + assert_list_almost_equal(hsv2rgb(0.5,1,1) , (0,1,1)) + assert_list_almost_equal(colors.hsv2rgb(180,100,100, normalised=False), (0,1,1)) + +def test_rgb2hls(): + assert_list_almost_equal(colors.rgb2hls(0,1,1) , (0.5,0.5,1)) + assert_list_almost_equal(colors.rgb2hls(0,255,255,normalised=False) , + (0.5,0.5,1)) + + assert_list_almost_equal(colors.hls2rgb(0.5,0.5,1), (0,1,1)) + assert_list_almost_equal(colors.hls2rgb(180, 50, 100, normalised=False), + (0.,1,1)) + +def test_hex2dec(): + assert colors.hex2dec("FF") == 1 + +def test_rgb2hex(): + colors.rgb2hex(0,0,255) + colors.rgb2hex(0,0,1) + colors.rgb2hex(*(0,0,1)) + try: + colors.rgb2hex([0,0]) + assert False + except: + assert True + + try: + colors.rgb2hex(0,0,1000) + assert False + except: + assert True + + try: + colors.rgb2hex(0,0,-1000) + assert False + except: + assert True + + try: + colors.rgb2hex(0,0,10, normalised=True) + assert False + except: + assert True + + +def testColors(): + # test constructors + c = colors.Color("#FFF") + c = colors.Color(rgb=(0,0,0)) + c = colors.Color(hls=(0,0,0)) + c = colors.Color(hsv=(0,0,0)) + c = colors.Color(c) + try: + colors.Color() + assert False + except: + assert True + try: + colors.Color(object) + assert False + except: + assert True + + + # test setter/getter + c = colors.Color("Blue") + assert c.rgb == (0, 0 ,1) + assert c.hex == "#0000FF" + assert_list_almost_equal( c.hsv, (0.66666666666666,1,1)) + assert_list_almost_equal(c.hls, (0.666666666666666, .5,1)) + print(c) + + c.normalised = True + c.name + c.hsv + c.hls + print(c) + assert c.rgb == (0,0,1) + c.rgb = (0,0,1) + c.hsv= (0,0,1) + + c.normalised = False + + # name can be changed and affects RGB/HEX + c.name = "Magenta" + assert c.rgb == colors._normalise(255, 0.0, 255) + + assert c.hex == "#FF00FF" + + # hex can be changed and affects name/HEX + c.hex = "#F8F8FF" + assert c.name == "Ghost White" # non official name + #assert c.rgb == + + # RGB can be changed and affects name/HEX + c.rgb = colors._normalise(248,248,255) + assert c.name == "Ghost White" # official name + assert c.hex == "#F8F8FF" + assert c.name == "Ghost White" # non official but works + assert c.hex == "#F8F8FF" + c.saturation_hls = 0.5 + assert c.saturation_hls == 0.5 + + c.lightness = 0.5 + assert c.lightness == 0.5 + c.hue = 0.5 + assert c.hue == 0.5 + + c.hex = "#FF1F1F" + assert c.name == "undefined" + try: + c.hex = "ZFF1F1F" + assert False + except: + assert True + + c = colors.Color("red") + assert c.red == 1 + assert c.green == 0 + assert c.blue == 0 + c.blue = 0. + c.green=0. + c.red = 0 + assert c.name == "Black" + c.value + c.value = 0.5 + c.yiq + + +def test_normalise(): + colors._normalise(255,255,255, mode='rgb') == (1,1,1) + colors._normalise(*(255,255,255), mode='rgb') == (1,1,1) + colors._normalise(*(360,100,100), mode='hls') == (1,1,1) + colors._denormalise(*(1,1,1), mode='rgb') == (255,255,255) + colors._denormalise(*(1,1,1), mode='hls') == (360,100,100) + +def test_to_intensity(): + to_intensity(0.5) + + +def test_colormap(): + try: + from pylab import close, clf, gcf + except: + return + c = Colormap() + cmap = c.get_cmap_heat() + #c.test_cmap(cmap) + f = gcf() + #f.close() + + + # design your own colormap + d = {'blue': [0,0,0,1,1,1,0], + 'green':[0,1,1,1,0,0,0], + 'red': [1,1,0,0,0,1,1]} + cmap = c.cmap(d, reverse=True) + cmap = c.get_cmap_rainbow() + cmap = c.get_cmap_red_green() + cmap = c.get_cmap_heat_r() + + + t = ['#FF0000FF', '#FF4D00FF', '#FF9900FF', '#FFE500FF', + '#CCFF00FF', '#80FF00FF', '#33FF00FF', '#00FF19FF', + '#00FF66FF', '#00FFB2FF', '#00FFFFFF', '#00B3FFFF', + '#0066FFFF', '#001AFFFF', '#3300FFFF', '#7F00FFFF', + '#CC00FFFF','#FF00E6FF','#FF0099FF', '#FF004DFF'] + # FIXME: need to find a way to close the plot. close('all') does not work + # c.plot_rgb_from_hex_list(t) + c.plot_colormap('misc') + #c.plot_colormap('jet') + c.test_colormap('jet') + c.diverging + c.colormaps + c.sequentials + c.sequentials2 + c.qualitative + + + t = ['#FF0000FF', '#FF4D00FF', '#FF9900FF','#FFE500FF', + '#CCFF00FF', '#80FF00FF','#33FF00FF', '#00FF19FF', + '#00FF66FF','#00FFB2FF','#00FFFFFF','#00B3FFFF', + '#0066FFFF','#001AFFFF','#3300FFFF','#7F00FFFF', + '#CC00FFFF','#FF00E6FF','#FF0099FF','#FF004DFF'] + c.plot_rgb_from_hex_list(t) + c.test_colormap() # no input plots the heat map + + +def test_HEX(): + + h = HEX() + h.get_standard_hex_color("0xFFF") + try: + h.get_standard_hex_color(22) + assert False + except: + assert True + + try: + h.get_standard_hex_color("r") + assert False + except: + assert True + + + try: + h.get_standard_hex_color("rrrrrrrrrrrr") + assert False + except: + assert True + + try: + h.get_standard_hex_color("#AAAZZZ") + assert False + except: + assert True + + try: + h.get_standard_hex_color("#AAAA") + assert False + except: + assert True + + diff --git a/test/test_get_cmap.py b/test/test_get_cmap.py new file mode 100644 index 0000000..3eb5a8a --- /dev/null +++ b/test/test_get_cmap.py @@ -0,0 +1,16 @@ +from colormap import cmap_builder as get_cmap + + +def test_get_cmap(): + get_cmap("heat") + get_cmap("heat_r") + get_cmap("nipy_spectral") + get_cmap("red_black_blue") + try: + get_cmap('dummy') + assert False + except: + assert True + + get_cmap('red', 'black', 'yellow') + get_cmap('red', 'black') -- Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/debian-med/python-colormap.git _______________________________________________ debian-med-commit mailing list [email protected] http://lists.alioth.debian.org/cgi-bin/mailman/listinfo/debian-med-commit
