Repository: vispy/vispy

Issue:
Adding .hex field to ColorArray
Would be an array of string with the hexadecimal code of RGB values. Useful when dealing with HTML backend.



Discussion:
+1 PR welcome


Resolving patch:
diff --git a/vispy/color/_color.py b/vispy/color/_color.py
--- a/vispy/color/_color.py
+++ b/vispy/color/_color.py
@@ -79,6 +79,30 @@ def _array_clip_val(val):
     return val
 
 
+###############################################################################
+# RGB<->HEX conversion
+
+def _hex_to_rgba(hexs):
+    """Convert hex to rgba, permitting alpha values in hex"""
+    hexs = np.atleast_1d(np.array(hexs, '|U9'))
+    out = np.ones((len(hexs), 4), np.float32)
+    for hi, h in enumerate(hexs):
+        assert isinstance(h, string_types)
+        off = 1 if h[0] == '#' else 0
+        assert len(h) in (6+off, 8+off)
+        e = (len(h)-off) // 2
+        out[hi, :e] = [int(h[i:i+2], 16) / 255.
+                       for i in range(off, len(h), 2)]
+    return out
+
+
+def _rgb_to_hex(rgbs):
+    """Convert rgb to hex triplet"""
+    rgbs, n_dim = _check_color_dim(rgbs)
+    return np.array(['#%02x%02x%02x' % tuple((255*rgb[:3]).astype(np.uint8))
+                     for rgb in rgbs], '|U7')
+
+
 ###############################################################################
 # RGB<->HSV conversion
 
@@ -313,7 +337,7 @@ def __getitem__(self, item):
         elif subrgba.ndim == 2:
             assert subrgba.shape[1] in (3, 4)
         return ColorArray(subrgba)
-        
+
     def __setitem__(self, item, value):
         if isinstance(item, tuple):
             raise ValueError('ColorArray indexing is only allowed along '
@@ -322,7 +346,7 @@ def __setitem__(self, item, value):
         if isinstance(value, ColorArray):
             value = value.rgba
         self._rgba[item] = value
-    
+
     # RGB(A)
     @property
     def rgba(self):
@@ -384,6 +408,18 @@ def alpha(self, val):
         """Set the color using alpha"""
         self._rgba[:, 3] = _array_clip_val(val)
 
+    ###########################################################################
+    # HEX
+    @property
+    def hex(self):
+        """Numpy array with N elements, each one a hex triplet string"""
+        return _rgb_to_hex(self._rgba)
+
+    @hex.setter
+    def hex(self, val):
+        """Set the color values using a list of hex strings"""
+        self.rgba = _hex_to_rgba(val)
+
     ###########################################################################
     # HSV
     @property
@@ -546,6 +582,10 @@ def RGB(self):
     def alpha(self):
         return super(Color, self).alpha[0]
 
+    @ColorArray.hex.getter
+    def hex(self):
+        return super(Color, self).hex[0]
+
     @ColorArray.hsv.getter
     def hsv(self):
         return super(Color, self).hsv[0]


Test patch:
diff --git a/vispy/color/tests/test_color.py b/vispy/color/tests/test_color.py
--- a/vispy/color/tests/test_color.py
+++ b/vispy/color/tests/test_color.py
@@ -21,6 +21,9 @@ def test_color():
     assert_equal(x.alpha, 1.)
     x.rgb = [0, 0, 1]
     assert_array_equal(x.hsv, [240, 1, 1])
+    assert_equal(x.hex, '#0000ff')
+    x.hex = '#00000000'
+    assert_array_equal(x.rgba, [0.]*4)
 
 
 def test_color_array():
@@ -85,8 +88,9 @@ def test_color_interpretation():
     r.alpha = 0
     r.rgb = (1, 0, 0)
     assert_equal(r.alpha, 0)
+    assert_equal(r.hex, ['#ff0000'])
     r.alpha = 1
-    r.rgb = 0, 1, 0
+    r.hex = '00ff00'
     assert_equal(r, ColorArray('g'))
     assert_array_equal(r.rgb.ravel(), (0., 1., 0.))
     r.RGB = 255, 0, 0