We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
ColorMap getLookupTable fails when alpha=None
<!-- In the following, please describe your issue in detail! -->
### Short description
The `getLookupTable` method of `pyqtgraph.ColorMap` fails to automatically determine whether alpha values should be included in a lookup table.

### Code to reproduce

```python
import pyqtgraph as pg

colors = [
    (0, 0, 0),
    (45, 5, 61),
    (84, 42, 55)
]
cmap = pg.ColorMap(pos=(0, 1, 2), color=colors)

cmap.getLookupTable(alpha=False)  # Works
cmap.getLookupTable(alpha=True)  # Works, but returned lookup table does not contain alpha values.
cmap.getLookupTable()  # Does not work
```

### Expected behavior
A lookup table is returned.

### Real behavior
The following exception is thrown:

```
Traceback (most recent call last):
  File "test.py", line 13, in <module>
    cmap.getLookupTable()  # Does not work
  File "...\venv\lib\site-packages\pyqtgraph\colormap.py", line 223, in getLookupTable
    alpha = self.usesAlpha()
  File "...\venv\lib\site-packages\pyqtgraph\colormap.py", line 236, in usesAlpha
    return np.any(self.color[:,3] != max)
IndexError: index 3 is out of bounds for axis 1 with size 3
```

### Tested environment(s)

 * PyQtGraph version: 0.11.0.dev0+gad7453c
 * Qt Python binding: 0.11.0.dev0+gad7453c
 * Python version: 3.7.3
 * NumPy version: 0.11.0.dev0+gad7453c
 * Operating system: Windows 10
 * Installation method: pip


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `pyqtgraph/colormap.py`
Content:
```
1 import numpy as np
2 from .Qt import QtGui, QtCore
3 from .python2_3 import basestring
4 
5 
6 class ColorMap(object):
7     """
8     A ColorMap defines a relationship between a scalar value and a range of colors. 
9     ColorMaps are commonly used for false-coloring monochromatic images, coloring 
10     scatter-plot points, and coloring surface plots by height. 
11     
12     Each color map is defined by a set of colors, each corresponding to a
13     particular scalar value. For example:
14     
15         | 0.0  -> black
16         | 0.2  -> red
17         | 0.6  -> yellow
18         | 1.0  -> white
19         
20     The colors for intermediate values are determined by interpolating between 
21     the two nearest colors in either RGB or HSV color space.
22     
23     To provide user-defined color mappings, see :class:`GradientWidget <pyqtgraph.GradientWidget>`.
24     """
25     
26     
27     ## color interpolation modes
28     RGB = 1
29     HSV_POS = 2
30     HSV_NEG = 3
31     
32     ## boundary modes
33     CLIP = 1
34     REPEAT = 2
35     MIRROR = 3
36     
37     ## return types
38     BYTE = 1
39     FLOAT = 2
40     QCOLOR = 3
41     
42     enumMap = {
43         'rgb': RGB,
44         'hsv+': HSV_POS,
45         'hsv-': HSV_NEG,
46         'clip': CLIP,
47         'repeat': REPEAT,
48         'mirror': MIRROR,
49         'byte': BYTE,
50         'float': FLOAT,
51         'qcolor': QCOLOR,
52     }
53     
54     def __init__(self, pos, color, mode=None):
55         """
56         ===============     ==============================================================
57         **Arguments:**
58         pos                 Array of positions where each color is defined
59         color               Array of RGBA colors.
60                             Integer data types are interpreted as 0-255; float data types
61                             are interpreted as 0.0-1.0
62         mode                Array of color modes (ColorMap.RGB, HSV_POS, or HSV_NEG)
63                             indicating the color space that should be used when
64                             interpolating between stops. Note that the last mode value is
65                             ignored. By default, the mode is entirely RGB.
66         ===============     ==============================================================
67         """
68         self.pos = np.array(pos)
69         order = np.argsort(self.pos)
70         self.pos = self.pos[order]
71         self.color = np.array(color)[order]
72         if mode is None:
73             mode = np.ones(len(pos))
74         self.mode = mode
75         self.stopsCache = {}
76         
77     def map(self, data, mode='byte'):
78         """
79         Return an array of colors corresponding to the values in *data*. 
80         Data must be either a scalar position or an array (any shape) of positions.
81         
82         The *mode* argument determines the type of data returned:
83         
84         =========== ===============================================================
85         byte        (default) Values are returned as 0-255 unsigned bytes.
86         float       Values are returned as 0.0-1.0 floats. 
87         qcolor      Values are returned as an array of QColor objects.
88         =========== ===============================================================
89         """
90         if isinstance(mode, basestring):
91             mode = self.enumMap[mode.lower()]
92             
93         if mode == self.QCOLOR:
94             pos, color = self.getStops(self.BYTE)
95         else:
96             pos, color = self.getStops(mode)
97             
98         # don't need this--np.interp takes care of it.
99         #data = np.clip(data, pos.min(), pos.max())
100             
101         # Interpolate
102         # TODO: is griddata faster?
103         #          interp = scipy.interpolate.griddata(pos, color, data)
104         if np.isscalar(data):
105             interp = np.empty((color.shape[1],), dtype=color.dtype)
106         else:
107             if not isinstance(data, np.ndarray):
108                 data = np.array(data)
109             interp = np.empty(data.shape + (color.shape[1],), dtype=color.dtype)
110         for i in range(color.shape[1]):
111             interp[...,i] = np.interp(data, pos, color[:,i])
112 
113         # Convert to QColor if requested
114         if mode == self.QCOLOR:
115             if np.isscalar(data):
116                 return QtGui.QColor(*interp)
117             else:
118                 return [QtGui.QColor(*x) for x in interp]
119         else:
120             return interp
121         
122     def mapToQColor(self, data):
123         """Convenience function; see :func:`map() <pyqtgraph.ColorMap.map>`."""
124         return self.map(data, mode=self.QCOLOR)
125 
126     def mapToByte(self, data):
127         """Convenience function; see :func:`map() <pyqtgraph.ColorMap.map>`."""
128         return self.map(data, mode=self.BYTE)
129 
130     def mapToFloat(self, data):
131         """Convenience function; see :func:`map() <pyqtgraph.ColorMap.map>`."""
132         return self.map(data, mode=self.FLOAT)
133     
134     def getGradient(self, p1=None, p2=None):
135         """Return a QLinearGradient object spanning from QPoints p1 to p2."""
136         if p1 == None:
137             p1 = QtCore.QPointF(0,0)
138         if p2 == None:
139             p2 = QtCore.QPointF(self.pos.max()-self.pos.min(),0)
140         g = QtGui.QLinearGradient(p1, p2)
141         
142         pos, color = self.getStops(mode=self.BYTE)
143         color = [QtGui.QColor(*x) for x in color]
144         g.setStops(list(zip(pos, color)))
145         
146         #if self.colorMode == 'rgb':
147             #ticks = self.listTicks()
148             #g.setStops([(x, QtGui.QColor(t.color)) for t,x in ticks])
149         #elif self.colorMode == 'hsv':  ## HSV mode is approximated for display by interpolating 10 points between each stop
150             #ticks = self.listTicks()
151             #stops = []
152             #stops.append((ticks[0][1], ticks[0][0].color))
153             #for i in range(1,len(ticks)):
154                 #x1 = ticks[i-1][1]
155                 #x2 = ticks[i][1]
156                 #dx = (x2-x1) / 10.
157                 #for j in range(1,10):
158                     #x = x1 + dx*j
159                     #stops.append((x, self.getColor(x)))
160                 #stops.append((x2, self.getColor(x2)))
161             #g.setStops(stops)
162         return g
163     
164     def getColors(self, mode=None):
165         """Return list of all color stops converted to the specified mode.
166         If mode is None, then no conversion is done."""
167         if isinstance(mode, basestring):
168             mode = self.enumMap[mode.lower()]
169         
170         color = self.color
171         if mode in [self.BYTE, self.QCOLOR] and color.dtype.kind == 'f':
172             color = (color * 255).astype(np.ubyte)
173         elif mode == self.FLOAT and color.dtype.kind != 'f':
174             color = color.astype(float) / 255.
175             
176         if mode == self.QCOLOR:
177             color = [QtGui.QColor(*x) for x in color]
178             
179         return color
180         
181     def getStops(self, mode):
182         ## Get fully-expanded set of RGBA stops in either float or byte mode.
183         if mode not in self.stopsCache:
184             color = self.color
185             if mode == self.BYTE and color.dtype.kind == 'f':
186                 color = (color * 255).astype(np.ubyte)
187             elif mode == self.FLOAT and color.dtype.kind != 'f':
188                 color = color.astype(float) / 255.
189         
190             ## to support HSV mode, we need to do a little more work..
191             #stops = []
192             #for i in range(len(self.pos)):
193                 #pos = self.pos[i]
194                 #color = color[i]
195                 
196                 #imode = self.mode[i]
197                 #if imode == self.RGB:
198                     #stops.append((x,color)) 
199                 #else:
200                     #ns = 
201             self.stopsCache[mode] = (self.pos, color)
202         return self.stopsCache[mode]
203         
204     def getLookupTable(self, start=0.0, stop=1.0, nPts=512, alpha=None, mode='byte'):
205         """
206         Return an RGB(A) lookup table (ndarray). 
207         
208         ===============   =============================================================================
209         **Arguments:**
210         start             The starting value in the lookup table (default=0.0)
211         stop              The final value in the lookup table (default=1.0)
212         nPts              The number of points in the returned lookup table.
213         alpha             True, False, or None - Specifies whether or not alpha values are included
214                           in the table. If alpha is None, it will be automatically determined.
215         mode              Determines return type: 'byte' (0-255), 'float' (0.0-1.0), or 'qcolor'.
216                           See :func:`map() <pyqtgraph.ColorMap.map>`.
217         ===============   =============================================================================
218         """
219         if isinstance(mode, basestring):
220             mode = self.enumMap[mode.lower()]
221         
222         if alpha is None:
223             alpha = self.usesAlpha()
224             
225         x = np.linspace(start, stop, nPts)
226         table = self.map(x, mode)
227         
228         if not alpha:
229             return table[:,:3]
230         else:
231             return table
232     
233     def usesAlpha(self):
234         """Return True if any stops have an alpha < 255"""
235         max = 1.0 if self.color.dtype.kind == 'f' else 255
236         return np.any(self.color[:,3] != max)
237             
238     def isMapTrivial(self):
239         """
240         Return True if the gradient has exactly two stops in it: black at 0.0 and white at 1.0.
241         """
242         if len(self.pos) != 2:
243             return False
244         if self.pos[0] != 0.0 or self.pos[1] != 1.0:
245             return False
246         if self.color.dtype.kind == 'f':
247             return np.all(self.color == np.array([[0.,0.,0.,1.], [1.,1.,1.,1.]]))
248         else:
249             return np.all(self.color == np.array([[0,0,0,255], [255,255,255,255]]))
250 
251     def __repr__(self):
252         pos = repr(self.pos).replace('\n', '')
253         color = repr(self.color).replace('\n', '')
254         return "ColorMap(%s, %s)" % (pos, color)
255
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/pyqtgraph/colormap.py b/pyqtgraph/colormap.py
--- a/pyqtgraph/colormap.py
+++ b/pyqtgraph/colormap.py
@@ -1,6 +1,7 @@
 import numpy as np
 from .Qt import QtGui, QtCore
 from .python2_3 import basestring
+from .functions import mkColor
 
 
 class ColorMap(object):
@@ -56,9 +57,9 @@
         ===============     ==============================================================
         **Arguments:**
         pos                 Array of positions where each color is defined
-        color               Array of RGBA colors.
-                            Integer data types are interpreted as 0-255; float data types
-                            are interpreted as 0.0-1.0
+        color               Array of colors.
+                            Values are interpreted via 
+                            :func:`mkColor() <pyqtgraph.mkColor>`.
         mode                Array of color modes (ColorMap.RGB, HSV_POS, or HSV_NEG)
                             indicating the color space that should be used when
                             interpolating between stops. Note that the last mode value is
@@ -68,7 +69,11 @@
         self.pos = np.array(pos)
         order = np.argsort(self.pos)
         self.pos = self.pos[order]
-        self.color = np.array(color)[order]
+        self.color = np.apply_along_axis(
+            func1d = lambda x: mkColor(x).getRgb(),
+            axis   = -1,
+            arr    = color,
+            )[order]
         if mode is None:
             mode = np.ones(len(pos))
         self.mode = mode
@@ -225,7 +230,7 @@
         x = np.linspace(start, stop, nPts)
         table = self.map(x, mode)
         
-        if not alpha:
+        if not alpha and mode != self.QCOLOR:
             return table[:,:3]
         else:
             return table

{"golden_diff": "diff --git a/pyqtgraph/colormap.py b/pyqtgraph/colormap.py\n--- a/pyqtgraph/colormap.py\n+++ b/pyqtgraph/colormap.py\n@@ -1,6 +1,7 @@\n import numpy as np\n from .Qt import QtGui, QtCore\n from .python2_3 import basestring\n+from .functions import mkColor\n \n \n class ColorMap(object):\n@@ -56,9 +57,9 @@\n         ===============     ==============================================================\n         **Arguments:**\n         pos                 Array of positions where each color is defined\n-        color               Array of RGBA colors.\n-                            Integer data types are interpreted as 0-255; float data types\n-                            are interpreted as 0.0-1.0\n+        color               Array of colors.\n+                            Values are interpreted via \n+                            :func:`mkColor() <pyqtgraph.mkColor>`.\n         mode                Array of color modes (ColorMap.RGB, HSV_POS, or HSV_NEG)\n                             indicating the color space that should be used when\n                             interpolating between stops. Note that the last mode value is\n@@ -68,7 +69,11 @@\n         self.pos = np.array(pos)\n         order = np.argsort(self.pos)\n         self.pos = self.pos[order]\n-        self.color = np.array(color)[order]\n+        self.color = np.apply_along_axis(\n+            func1d = lambda x: mkColor(x).getRgb(),\n+            axis   = -1,\n+            arr    = color,\n+            )[order]\n         if mode is None:\n             mode = np.ones(len(pos))\n         self.mode = mode\n@@ -225,7 +230,7 @@\n         x = np.linspace(start, stop, nPts)\n         table = self.map(x, mode)\n         \n-        if not alpha:\n+        if not alpha and mode != self.QCOLOR:\n             return table[:,:3]\n         else:\n             return table\n", "issue": "ColorMap getLookupTable fails when alpha=None\n<!-- In the following, please describe your issue in detail! -->\r\n### Short description\r\nThe `getLookupTable` method of `pyqtgraph.ColorMap` fails to automatically determine whether alpha values should be included in a lookup table.\r\n\r\n### Code to reproduce\r\n\r\n```python\r\nimport pyqtgraph as pg\r\n\r\ncolors = [\r\n    (0, 0, 0),\r\n    (45, 5, 61),\r\n    (84, 42, 55)\r\n]\r\ncmap = pg.ColorMap(pos=(0, 1, 2), color=colors)\r\n\r\ncmap.getLookupTable(alpha=False)  # Works\r\ncmap.getLookupTable(alpha=True)  # Works, but returned lookup table does not contain alpha values.\r\ncmap.getLookupTable()  # Does not work\r\n```\r\n\r\n### Expected behavior\r\nA lookup table is returned.\r\n\r\n### Real behavior\r\nThe following exception is thrown:\r\n\r\n```\r\nTraceback (most recent call last):\r\n  File \"test.py\", line 13, in <module>\r\n    cmap.getLookupTable()  # Does not work\r\n  File \"...\\venv\\lib\\site-packages\\pyqtgraph\\colormap.py\", line 223, in getLookupTable\r\n    alpha = self.usesAlpha()\r\n  File \"...\\venv\\lib\\site-packages\\pyqtgraph\\colormap.py\", line 236, in usesAlpha\r\n    return np.any(self.color[:,3] != max)\r\nIndexError: index 3 is out of bounds for axis 1 with size 3\r\n```\r\n\r\n### Tested environment(s)\r\n\r\n * PyQtGraph version: 0.11.0.dev0+gad7453c\r\n * Qt Python binding: 0.11.0.dev0+gad7453c\r\n * Python version: 3.7.3\r\n * NumPy version: 0.11.0.dev0+gad7453c\r\n * Operating system: Windows 10\r\n * Installation method: pip\r\n\n", "before_files": [{"content": "import numpy as np\nfrom .Qt import QtGui, QtCore\nfrom .python2_3 import basestring\n\n\nclass ColorMap(object):\n    \"\"\"\n    A ColorMap defines a relationship between a scalar value and a range of colors. \n    ColorMaps are commonly used for false-coloring monochromatic images, coloring \n    scatter-plot points, and coloring surface plots by height. \n    \n    Each color map is defined by a set of colors, each corresponding to a\n    particular scalar value. For example:\n    \n        | 0.0  -> black\n        | 0.2  -> red\n        | 0.6  -> yellow\n        | 1.0  -> white\n        \n    The colors for intermediate values are determined by interpolating between \n    the two nearest colors in either RGB or HSV color space.\n    \n    To provide user-defined color mappings, see :class:`GradientWidget <pyqtgraph.GradientWidget>`.\n    \"\"\"\n    \n    \n    ## color interpolation modes\n    RGB = 1\n    HSV_POS = 2\n    HSV_NEG = 3\n    \n    ## boundary modes\n    CLIP = 1\n    REPEAT = 2\n    MIRROR = 3\n    \n    ## return types\n    BYTE = 1\n    FLOAT = 2\n    QCOLOR = 3\n    \n    enumMap = {\n        'rgb': RGB,\n        'hsv+': HSV_POS,\n        'hsv-': HSV_NEG,\n        'clip': CLIP,\n        'repeat': REPEAT,\n        'mirror': MIRROR,\n        'byte': BYTE,\n        'float': FLOAT,\n        'qcolor': QCOLOR,\n    }\n    \n    def __init__(self, pos, color, mode=None):\n        \"\"\"\n        ===============     ==============================================================\n        **Arguments:**\n        pos                 Array of positions where each color is defined\n        color               Array of RGBA colors.\n                            Integer data types are interpreted as 0-255; float data types\n                            are interpreted as 0.0-1.0\n        mode                Array of color modes (ColorMap.RGB, HSV_POS, or HSV_NEG)\n                            indicating the color space that should be used when\n                            interpolating between stops. Note that the last mode value is\n                            ignored. By default, the mode is entirely RGB.\n        ===============     ==============================================================\n        \"\"\"\n        self.pos = np.array(pos)\n        order = np.argsort(self.pos)\n        self.pos = self.pos[order]\n        self.color = np.array(color)[order]\n        if mode is None:\n            mode = np.ones(len(pos))\n        self.mode = mode\n        self.stopsCache = {}\n        \n    def map(self, data, mode='byte'):\n        \"\"\"\n        Return an array of colors corresponding to the values in *data*. \n        Data must be either a scalar position or an array (any shape) of positions.\n        \n        The *mode* argument determines the type of data returned:\n        \n        =========== ===============================================================\n        byte        (default) Values are returned as 0-255 unsigned bytes.\n        float       Values are returned as 0.0-1.0 floats. \n        qcolor      Values are returned as an array of QColor objects.\n        =========== ===============================================================\n        \"\"\"\n        if isinstance(mode, basestring):\n            mode = self.enumMap[mode.lower()]\n            \n        if mode == self.QCOLOR:\n            pos, color = self.getStops(self.BYTE)\n        else:\n            pos, color = self.getStops(mode)\n            \n        # don't need this--np.interp takes care of it.\n        #data = np.clip(data, pos.min(), pos.max())\n            \n        # Interpolate\n        # TODO: is griddata faster?\n        #          interp = scipy.interpolate.griddata(pos, color, data)\n        if np.isscalar(data):\n            interp = np.empty((color.shape[1],), dtype=color.dtype)\n        else:\n            if not isinstance(data, np.ndarray):\n                data = np.array(data)\n            interp = np.empty(data.shape + (color.shape[1],), dtype=color.dtype)\n        for i in range(color.shape[1]):\n            interp[...,i] = np.interp(data, pos, color[:,i])\n\n        # Convert to QColor if requested\n        if mode == self.QCOLOR:\n            if np.isscalar(data):\n                return QtGui.QColor(*interp)\n            else:\n                return [QtGui.QColor(*x) for x in interp]\n        else:\n            return interp\n        \n    def mapToQColor(self, data):\n        \"\"\"Convenience function; see :func:`map() <pyqtgraph.ColorMap.map>`.\"\"\"\n        return self.map(data, mode=self.QCOLOR)\n\n    def mapToByte(self, data):\n        \"\"\"Convenience function; see :func:`map() <pyqtgraph.ColorMap.map>`.\"\"\"\n        return self.map(data, mode=self.BYTE)\n\n    def mapToFloat(self, data):\n        \"\"\"Convenience function; see :func:`map() <pyqtgraph.ColorMap.map>`.\"\"\"\n        return self.map(data, mode=self.FLOAT)\n    \n    def getGradient(self, p1=None, p2=None):\n        \"\"\"Return a QLinearGradient object spanning from QPoints p1 to p2.\"\"\"\n        if p1 == None:\n            p1 = QtCore.QPointF(0,0)\n        if p2 == None:\n            p2 = QtCore.QPointF(self.pos.max()-self.pos.min(),0)\n        g = QtGui.QLinearGradient(p1, p2)\n        \n        pos, color = self.getStops(mode=self.BYTE)\n        color = [QtGui.QColor(*x) for x in color]\n        g.setStops(list(zip(pos, color)))\n        \n        #if self.colorMode == 'rgb':\n            #ticks = self.listTicks()\n            #g.setStops([(x, QtGui.QColor(t.color)) for t,x in ticks])\n        #elif self.colorMode == 'hsv':  ## HSV mode is approximated for display by interpolating 10 points between each stop\n            #ticks = self.listTicks()\n            #stops = []\n            #stops.append((ticks[0][1], ticks[0][0].color))\n            #for i in range(1,len(ticks)):\n                #x1 = ticks[i-1][1]\n                #x2 = ticks[i][1]\n                #dx = (x2-x1) / 10.\n                #for j in range(1,10):\n                    #x = x1 + dx*j\n                    #stops.append((x, self.getColor(x)))\n                #stops.append((x2, self.getColor(x2)))\n            #g.setStops(stops)\n        return g\n    \n    def getColors(self, mode=None):\n        \"\"\"Return list of all color stops converted to the specified mode.\n        If mode is None, then no conversion is done.\"\"\"\n        if isinstance(mode, basestring):\n            mode = self.enumMap[mode.lower()]\n        \n        color = self.color\n        if mode in [self.BYTE, self.QCOLOR] and color.dtype.kind == 'f':\n            color = (color * 255).astype(np.ubyte)\n        elif mode == self.FLOAT and color.dtype.kind != 'f':\n            color = color.astype(float) / 255.\n            \n        if mode == self.QCOLOR:\n            color = [QtGui.QColor(*x) for x in color]\n            \n        return color\n        \n    def getStops(self, mode):\n        ## Get fully-expanded set of RGBA stops in either float or byte mode.\n        if mode not in self.stopsCache:\n            color = self.color\n            if mode == self.BYTE and color.dtype.kind == 'f':\n                color = (color * 255).astype(np.ubyte)\n            elif mode == self.FLOAT and color.dtype.kind != 'f':\n                color = color.astype(float) / 255.\n        \n            ## to support HSV mode, we need to do a little more work..\n            #stops = []\n            #for i in range(len(self.pos)):\n                #pos = self.pos[i]\n                #color = color[i]\n                \n                #imode = self.mode[i]\n                #if imode == self.RGB:\n                    #stops.append((x,color)) \n                #else:\n                    #ns = \n            self.stopsCache[mode] = (self.pos, color)\n        return self.stopsCache[mode]\n        \n    def getLookupTable(self, start=0.0, stop=1.0, nPts=512, alpha=None, mode='byte'):\n        \"\"\"\n        Return an RGB(A) lookup table (ndarray). \n        \n        ===============   =============================================================================\n        **Arguments:**\n        start             The starting value in the lookup table (default=0.0)\n        stop              The final value in the lookup table (default=1.0)\n        nPts              The number of points in the returned lookup table.\n        alpha             True, False, or None - Specifies whether or not alpha values are included\n                          in the table. If alpha is None, it will be automatically determined.\n        mode              Determines return type: 'byte' (0-255), 'float' (0.0-1.0), or 'qcolor'.\n                          See :func:`map() <pyqtgraph.ColorMap.map>`.\n        ===============   =============================================================================\n        \"\"\"\n        if isinstance(mode, basestring):\n            mode = self.enumMap[mode.lower()]\n        \n        if alpha is None:\n            alpha = self.usesAlpha()\n            \n        x = np.linspace(start, stop, nPts)\n        table = self.map(x, mode)\n        \n        if not alpha:\n            return table[:,:3]\n        else:\n            return table\n    \n    def usesAlpha(self):\n        \"\"\"Return True if any stops have an alpha < 255\"\"\"\n        max = 1.0 if self.color.dtype.kind == 'f' else 255\n        return np.any(self.color[:,3] != max)\n            \n    def isMapTrivial(self):\n        \"\"\"\n        Return True if the gradient has exactly two stops in it: black at 0.0 and white at 1.0.\n        \"\"\"\n        if len(self.pos) != 2:\n            return False\n        if self.pos[0] != 0.0 or self.pos[1] != 1.0:\n            return False\n        if self.color.dtype.kind == 'f':\n            return np.all(self.color == np.array([[0.,0.,0.,1.], [1.,1.,1.,1.]]))\n        else:\n            return np.all(self.color == np.array([[0,0,0,255], [255,255,255,255]]))\n\n    def __repr__(self):\n        pos = repr(self.pos).replace('\\n', '')\n        color = repr(self.color).replace('\\n', '')\n        return \"ColorMap(%s, %s)\" % (pos, color)\n", "path": "pyqtgraph/colormap.py"}], "after_files": [{"content": "import numpy as np\nfrom .Qt import QtGui, QtCore\nfrom .python2_3 import basestring\nfrom .functions import mkColor\n\n\nclass ColorMap(object):\n    \"\"\"\n    A ColorMap defines a relationship between a scalar value and a range of colors. \n    ColorMaps are commonly used for false-coloring monochromatic images, coloring \n    scatter-plot points, and coloring surface plots by height. \n    \n    Each color map is defined by a set of colors, each corresponding to a\n    particular scalar value. For example:\n    \n        | 0.0  -> black\n        | 0.2  -> red\n        | 0.6  -> yellow\n        | 1.0  -> white\n        \n    The colors for intermediate values are determined by interpolating between \n    the two nearest colors in either RGB or HSV color space.\n    \n    To provide user-defined color mappings, see :class:`GradientWidget <pyqtgraph.GradientWidget>`.\n    \"\"\"\n    \n    \n    ## color interpolation modes\n    RGB = 1\n    HSV_POS = 2\n    HSV_NEG = 3\n    \n    ## boundary modes\n    CLIP = 1\n    REPEAT = 2\n    MIRROR = 3\n    \n    ## return types\n    BYTE = 1\n    FLOAT = 2\n    QCOLOR = 3\n    \n    enumMap = {\n        'rgb': RGB,\n        'hsv+': HSV_POS,\n        'hsv-': HSV_NEG,\n        'clip': CLIP,\n        'repeat': REPEAT,\n        'mirror': MIRROR,\n        'byte': BYTE,\n        'float': FLOAT,\n        'qcolor': QCOLOR,\n    }\n    \n    def __init__(self, pos, color, mode=None):\n        \"\"\"\n        ===============     ==============================================================\n        **Arguments:**\n        pos                 Array of positions where each color is defined\n        color               Array of colors.\n                            Values are interpreted via \n                            :func:`mkColor() <pyqtgraph.mkColor>`.\n        mode                Array of color modes (ColorMap.RGB, HSV_POS, or HSV_NEG)\n                            indicating the color space that should be used when\n                            interpolating between stops. Note that the last mode value is\n                            ignored. By default, the mode is entirely RGB.\n        ===============     ==============================================================\n        \"\"\"\n        self.pos = np.array(pos)\n        order = np.argsort(self.pos)\n        self.pos = self.pos[order]\n        self.color = np.apply_along_axis(\n            func1d = lambda x: mkColor(x).getRgb(),\n            axis   = -1,\n            arr    = color,\n            )[order]\n        if mode is None:\n            mode = np.ones(len(pos))\n        self.mode = mode\n        self.stopsCache = {}\n        \n    def map(self, data, mode='byte'):\n        \"\"\"\n        Return an array of colors corresponding to the values in *data*. \n        Data must be either a scalar position or an array (any shape) of positions.\n        \n        The *mode* argument determines the type of data returned:\n        \n        =========== ===============================================================\n        byte        (default) Values are returned as 0-255 unsigned bytes.\n        float       Values are returned as 0.0-1.0 floats. \n        qcolor      Values are returned as an array of QColor objects.\n        =========== ===============================================================\n        \"\"\"\n        if isinstance(mode, basestring):\n            mode = self.enumMap[mode.lower()]\n            \n        if mode == self.QCOLOR:\n            pos, color = self.getStops(self.BYTE)\n        else:\n            pos, color = self.getStops(mode)\n            \n        # don't need this--np.interp takes care of it.\n        #data = np.clip(data, pos.min(), pos.max())\n            \n        # Interpolate\n        # TODO: is griddata faster?\n        #          interp = scipy.interpolate.griddata(pos, color, data)\n        if np.isscalar(data):\n            interp = np.empty((color.shape[1],), dtype=color.dtype)\n        else:\n            if not isinstance(data, np.ndarray):\n                data = np.array(data)\n            interp = np.empty(data.shape + (color.shape[1],), dtype=color.dtype)\n        for i in range(color.shape[1]):\n            interp[...,i] = np.interp(data, pos, color[:,i])\n\n        # Convert to QColor if requested\n        if mode == self.QCOLOR:\n            if np.isscalar(data):\n                return QtGui.QColor(*interp)\n            else:\n                return [QtGui.QColor(*x) for x in interp]\n        else:\n            return interp\n        \n    def mapToQColor(self, data):\n        \"\"\"Convenience function; see :func:`map() <pyqtgraph.ColorMap.map>`.\"\"\"\n        return self.map(data, mode=self.QCOLOR)\n\n    def mapToByte(self, data):\n        \"\"\"Convenience function; see :func:`map() <pyqtgraph.ColorMap.map>`.\"\"\"\n        return self.map(data, mode=self.BYTE)\n\n    def mapToFloat(self, data):\n        \"\"\"Convenience function; see :func:`map() <pyqtgraph.ColorMap.map>`.\"\"\"\n        return self.map(data, mode=self.FLOAT)\n    \n    def getGradient(self, p1=None, p2=None):\n        \"\"\"Return a QLinearGradient object spanning from QPoints p1 to p2.\"\"\"\n        if p1 == None:\n            p1 = QtCore.QPointF(0,0)\n        if p2 == None:\n            p2 = QtCore.QPointF(self.pos.max()-self.pos.min(),0)\n        g = QtGui.QLinearGradient(p1, p2)\n        \n        pos, color = self.getStops(mode=self.BYTE)\n        color = [QtGui.QColor(*x) for x in color]\n        g.setStops(list(zip(pos, color)))\n        \n        #if self.colorMode == 'rgb':\n            #ticks = self.listTicks()\n            #g.setStops([(x, QtGui.QColor(t.color)) for t,x in ticks])\n        #elif self.colorMode == 'hsv':  ## HSV mode is approximated for display by interpolating 10 points between each stop\n            #ticks = self.listTicks()\n            #stops = []\n            #stops.append((ticks[0][1], ticks[0][0].color))\n            #for i in range(1,len(ticks)):\n                #x1 = ticks[i-1][1]\n                #x2 = ticks[i][1]\n                #dx = (x2-x1) / 10.\n                #for j in range(1,10):\n                    #x = x1 + dx*j\n                    #stops.append((x, self.getColor(x)))\n                #stops.append((x2, self.getColor(x2)))\n            #g.setStops(stops)\n        return g\n    \n    def getColors(self, mode=None):\n        \"\"\"Return list of all color stops converted to the specified mode.\n        If mode is None, then no conversion is done.\"\"\"\n        if isinstance(mode, basestring):\n            mode = self.enumMap[mode.lower()]\n        \n        color = self.color\n        if mode in [self.BYTE, self.QCOLOR] and color.dtype.kind == 'f':\n            color = (color * 255).astype(np.ubyte)\n        elif mode == self.FLOAT and color.dtype.kind != 'f':\n            color = color.astype(float) / 255.\n            \n        if mode == self.QCOLOR:\n            color = [QtGui.QColor(*x) for x in color]\n            \n        return color\n        \n    def getStops(self, mode):\n        ## Get fully-expanded set of RGBA stops in either float or byte mode.\n        if mode not in self.stopsCache:\n            color = self.color\n            if mode == self.BYTE and color.dtype.kind == 'f':\n                color = (color * 255).astype(np.ubyte)\n            elif mode == self.FLOAT and color.dtype.kind != 'f':\n                color = color.astype(float) / 255.\n        \n            ## to support HSV mode, we need to do a little more work..\n            #stops = []\n            #for i in range(len(self.pos)):\n                #pos = self.pos[i]\n                #color = color[i]\n                \n                #imode = self.mode[i]\n                #if imode == self.RGB:\n                    #stops.append((x,color)) \n                #else:\n                    #ns = \n            self.stopsCache[mode] = (self.pos, color)\n        return self.stopsCache[mode]\n        \n    def getLookupTable(self, start=0.0, stop=1.0, nPts=512, alpha=None, mode='byte'):\n        \"\"\"\n        Return an RGB(A) lookup table (ndarray). \n        \n        ===============   =============================================================================\n        **Arguments:**\n        start             The starting value in the lookup table (default=0.0)\n        stop              The final value in the lookup table (default=1.0)\n        nPts              The number of points in the returned lookup table.\n        alpha             True, False, or None - Specifies whether or not alpha values are included\n                          in the table. If alpha is None, it will be automatically determined.\n        mode              Determines return type: 'byte' (0-255), 'float' (0.0-1.0), or 'qcolor'.\n                          See :func:`map() <pyqtgraph.ColorMap.map>`.\n        ===============   =============================================================================\n        \"\"\"\n        if isinstance(mode, basestring):\n            mode = self.enumMap[mode.lower()]\n        \n        if alpha is None:\n            alpha = self.usesAlpha()\n            \n        x = np.linspace(start, stop, nPts)\n        table = self.map(x, mode)\n        \n        if not alpha and mode != self.QCOLOR:\n            return table[:,:3]\n        else:\n            return table\n    \n    def usesAlpha(self):\n        \"\"\"Return True if any stops have an alpha < 255\"\"\"\n        max = 1.0 if self.color.dtype.kind == 'f' else 255\n        return np.any(self.color[:,3] != max)\n            \n    def isMapTrivial(self):\n        \"\"\"\n        Return True if the gradient has exactly two stops in it: black at 0.0 and white at 1.0.\n        \"\"\"\n        if len(self.pos) != 2:\n            return False\n        if self.pos[0] != 0.0 or self.pos[1] != 1.0:\n            return False\n        if self.color.dtype.kind == 'f':\n            return np.all(self.color == np.array([[0.,0.,0.,1.], [1.,1.,1.,1.]]))\n        else:\n            return np.all(self.color == np.array([[0,0,0,255], [255,255,255,255]]))\n\n    def __repr__(self):\n        pos = repr(self.pos).replace('\\n', '')\n        color = repr(self.color).replace('\\n', '')\n        return \"ColorMap(%s, %s)\" % (pos, color)\n", "path": "pyqtgraph/colormap.py"}]}