2
votes

I get an error when I plot with colours, and works fine without it. My line colours need to be restricted to 2 defined values.

This works in Jupyter Notebook

import random
xStart = random.sample(range(1, 10), 6)
xStart.sort()
xEnd = [x + random.randint(1, 6) for x in xStart]
yval = list(range(1, 7))
colours = ['r']*6
colours[1] = 'b'
print(xStart)
print(xEnd)
print(yval)
print(colours)
f, ax1 = plt.subplots(figsize=(6,4))
ax1.plot([xStart,xEnd], [yval,yval], '-', linewidth=1) #, color=colours)
plt.show()

Multiple line segments

This does not work. If I uncomment the color argument, the code throws an (elaborate) error. While I can draw each line segment in a loop and colour each red or blue, I assume it will be slower than the below code. In this toy example I have 6 lines, but in reality I have 12,000 lines and it takes a few minutes, drawing one line at a time in a loop.

I think the error is related to the size of my colour argument; it is likely expecting 1 (at a time internally) whereas I am providing a list of 6.

import random
xStart = random.sample(range(1, 10), 6)
xStart.sort()
xEnd = [x + random.randint(1, 6) for x in xStart]
yval = list(range(1, 7))
colours = ['r']*6
colours[1] = 'b'
print(xStart)
print(xEnd)
print(yval)
print(colours)
f, ax1 = plt.subplots(figsize=(6,4))
ax1.plot([xStart,xEnd], [yval,yval], '-', linewidth=1, color=colours)  #--> Only change from above code
plt.show()

TypeError Traceback (most recent call last) C:\Anaconda3\lib\site-packages\matplotlib\colors.py in to_rgba(c, alpha) 131 try: --> 132 rgba = _colors_full_map.cache[c, alpha] 133 except (KeyError, TypeError): # Not in cache, or unhashable.

TypeError: unhashable type: 'list'

During handling of the above exception, another exception occurred:

ValueError Traceback (most recent call last) C:\Anaconda3\lib\site-packages\IPython\core\formatters.py in call(self, obj) 339 pass 340 else: --> 341 return printer(obj) 342 # Finally look for special method names 343 method = get_real_method(obj, self.print_method)

C:\Anaconda3\lib\site-packages\IPython\core\pylabtools.py in (fig) 236 237 if 'png' in formats: --> 238 png_formatter.for_type(Figure, lambda fig: print_figure(fig, 'png', **kwargs)) 239 if 'retina' in formats or 'png2x' in formats: 240 png_formatter.for_type(Figure, lambda fig: retina_figure(fig, **kwargs))

C:\Anaconda3\lib\site-packages\IPython\core\pylabtools.py in print_figure(fig, fmt, bbox_inches, **kwargs) 120 121 bytes_io = BytesIO() --> 122 fig.canvas.print_figure(bytes_io, **kw) 123 data = bytes_io.getvalue() 124 if fmt == 'svg':

C:\Anaconda3\lib\site-packages\matplotlib\backend_bases.py in print_figure(self, filename, dpi, facecolor, edgecolor, orientation, format, **kwargs) 2214 orientation=orientation, 2215 dryrun=True, -> 2216 **kwargs) 2217 renderer = self.figure._cachedRenderer 2218 bbox_inches = self.figure.get_tightbbox(renderer)

C:\Anaconda3\lib\site-packages\matplotlib\backends\backend_agg.py in print_png(self, filename_or_obj, *args, **kwargs) 505 506 def print_png(self, filename_or_obj, *args, **kwargs): --> 507 FigureCanvasAgg.draw(self) 508 renderer = self.get_renderer() 509 original_dpi = renderer.dpi

C:\Anaconda3\lib\site-packages\matplotlib\backends\backend_agg.py in draw(self) 428 # if toolbar: 429 # toolbar.set_cursor(cursors.WAIT) --> 430 self.figure.draw(self.renderer) 431 finally: 432 # if toolbar:

C:\Anaconda3\lib\site-packages\matplotlib\artist.py in draw_wrapper(artist, renderer, *args, **kwargs) 53 renderer.start_filter() 54 ---> 55 return draw(artist, renderer, *args, **kwargs) 56 finally: 57 if artist.get_agg_filter() is not None:

C:\Anaconda3\lib\site-packages\matplotlib\figure.py in draw(self, renderer) 1297 1298
mimage._draw_list_compositing_images( -> 1299 renderer, self, artists, self.suppressComposite) 1300 1301
renderer.close_group('figure')

C:\Anaconda3\lib\site-packages\matplotlib\image.py in _draw_list_compositing_images(renderer, parent, artists, suppress_composite) 136 if not_composite or not has_images: 137 for a in artists: --> 138 a.draw(renderer) 139 else: 140 # Composite any adjacent images together

C:\Anaconda3\lib\site-packages\matplotlib\artist.py in draw_wrapper(artist, renderer, *args, **kwargs) 53 renderer.start_filter() 54 ---> 55 return draw(artist, renderer, *args, **kwargs) 56 finally: 57 if artist.get_agg_filter() is not None:

C:\Anaconda3\lib\site-packages\matplotlib\axes_base.py in draw(self, renderer, inframe) 2435 renderer.stop_rasterizing()
2436 -> 2437 mimage._draw_list_compositing_images(renderer, self, artists) 2438 2439 renderer.close_group('axes')

C:\Anaconda3\lib\site-packages\matplotlib\image.py in _draw_list_compositing_images(renderer, parent, artists, suppress_composite) 136 if not_composite or not has_images: 137 for a in artists: --> 138 a.draw(renderer) 139 else: 140 # Composite any adjacent images together

C:\Anaconda3\lib\site-packages\matplotlib\artist.py in draw_wrapper(artist, renderer, *args, **kwargs) 53 renderer.start_filter() 54 ---> 55 return draw(artist, renderer, *args, **kwargs) 56 finally: 57 if artist.get_agg_filter() is not None:

C:\Anaconda3\lib\site-packages\matplotlib\lines.py in draw(self, renderer) 765 self._set_gc_clip(gc) 766 --> 767 ln_color_rgba = self._get_rgba_ln_color() 768 gc.set_foreground(ln_color_rgba, isRGBA=True) 769 gc.set_alpha(ln_color_rgba[3])

C:\Anaconda3\lib\site-packages\matplotlib\lines.py in _get_rgba_ln_color(self, alt) 1267 1268 def _get_rgba_ln_color(self, alt=False): -> 1269 return mcolors.to_rgba(self._color, self._alpha) 1270 1271 # some aliases....

C:\Anaconda3\lib\site-packages\matplotlib\colors.py in to_rgba(c, alpha) 132 rgba = _colors_full_map.cache[c, alpha] 133 except (KeyError, TypeError): # Not in cache, or unhashable. --> 134 rgba = _to_rgba_no_colorcycle(c, alpha) 135 try: 136 _colors_full_map.cache[c, alpha] = rgba

C:\Anaconda3\lib\site-packages\matplotlib\colors.py in _to_rgba_no_colorcycle(c, alpha) 183 # float)andnp.array(...).astype(float)` all convert "0.5" to 0.5. 184 # Test dimensionality to reject single floats. --> 185 raise ValueError("Invalid RGBA argument: {!r}".format(orig_c)) 186 # Return a tuple to prevent the cached value from being modified. 187 c = tuple(c.astype(float))

ValueError: Invalid RGBA argument: ['r', 'b', 'r', 'r', 'r', 'r']

1
You will get answers here and hereSheldore
I do not believe it is a duplicate of <a href="stackoverflow.com/questions/4805048/… to get different colored lines for different plots in a single figure?</a> since I read through that earlier and it did not help. Here I am drawing multiple lines with one ax.plot() command and that is why the colour argument is not working.Anand
Look at this answer on the link you shared. You can first plot the lines using your axis handle ax and then later change the line colors using predefined colorsSheldore
Bazingaa, You are a genius! Thanks that worked like a champion :) Is there a way I can upvote your answer also? I have upvoted the other thread.Anand

1 Answers

2
votes

OK thanks to Bazingaa and this thread, How to get different colored lines for different plots in a single figure?

...the final code is as follows.

Since I am drawing multiple lines with one ax.plot() command, the colour argument will not take. IMHO it should since it logically makes sense and should be an enhancement matplotlib does. Nonetheless, here is the solution as Bazingaa pointed out to me.

For those interested, as expected this code does run a LOT faster compared with drawing 12K lines in a loop (in order to draw & color them one at a time with individual ax.plot() commands).

import random
xStart = random.sample(range(1, 10), 6)
xStart.sort()
xEnd = [x + random.randint(1, 6) for x in xStart]
yval = list(range(1, 7))
colours = ['r']*6
colours[1] = 'b'
f, ax1 = plt.subplots(figsize=(6,4))
ax1.plot([xStart,xEnd], [yval,yval], '-', linewidth=1) #, color=colours)  #Leaving the color argument commented
#Add new code to colour after the fact
for idx,line in enumerate(ax1.lines):
        line.set_color(colours[idx])
plt.show()