mplstereonet icon indicating copy to clipboard operation
mplstereonet copied to clipboard

Cannot plot with a list of colors

Open creuzige opened this issue 5 years ago • 1 comments

I have been trying to plot a list of poles, each pole with an individual color also stored in a list. If I run this as a scatter plot (see code below), the plot executes normally. (Matplotlib 3.1.1)

fig = plt.figure(figsize=(3,3), dpi=300) ax1 = fig.add_subplot(111) ax1.scatter([1,2,3],[4,5,6],color=['red','green','blue']) plt.show()

However, if I try the same thing with 'pole':

fig = plt.figure(figsize=(3,3), dpi=300) ax1 = fig.add_subplot(111, projection='stereonet') ax1.pole([1,2,3],[4,5,6],color=['red','green','blue']) plt.show()

I get the following error message:


TypeError Traceback (most recent call last) ~/anaconda2/envs/SNS-Analysis-py36/lib/python3.6/site-packages/matplotlib/colors.py in to_rgba(c, alpha) 173 try: --> 174 rgba = _colors_full_map.cache[c, alpha] 175 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) ~/anaconda2/envs/SNS-Analysis-py36/lib/python3.6/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)

~/anaconda2/envs/SNS-Analysis-py36/lib/python3.6/site-packages/IPython/core/pylabtools.py in (fig) 242 243 if 'png' in formats: --> 244 png_formatter.for_type(Figure, lambda fig: print_figure(fig, 'png', **kwargs)) 245 if 'retina' in formats or 'png2x' in formats: 246 png_formatter.for_type(Figure, lambda fig: retina_figure(fig, **kwargs))

~/anaconda2/envs/SNS-Analysis-py36/lib/python3.6/site-packages/IPython/core/pylabtools.py in print_figure(fig, fmt, bbox_inches, **kwargs) 126 127 bytes_io = BytesIO() --> 128 fig.canvas.print_figure(bytes_io, **kw) 129 data = bytes_io.getvalue() 130 if fmt == 'svg':

~/anaconda2/envs/SNS-Analysis-py36/lib/python3.6/site-packages/matplotlib/backend_bases.py in print_figure(self, filename, dpi, facecolor, edgecolor, orientation, format, bbox_inches, **kwargs) 2047 orientation=orientation, 2048 dryrun=True, -> 2049 **kwargs) 2050 renderer = self.figure._cachedRenderer 2051 bbox_artists = kwargs.pop("bbox_extra_artists", None)

~/anaconda2/envs/SNS-Analysis-py36/lib/python3.6/site-packages/matplotlib/backends/backend_agg.py in print_png(self, filename_or_obj, *args, **kwargs) 508 509 """ --> 510 FigureCanvasAgg.draw(self) 511 renderer = self.get_renderer() 512

~/anaconda2/envs/SNS-Analysis-py36/lib/python3.6/site-packages/matplotlib/backends/backend_agg.py in draw(self) 400 toolbar = self.toolbar 401 try: --> 402 self.figure.draw(self.renderer) 403 # A GUI class may be need to update a window using this draw, so 404 # don't forget to call the superclass.

~/anaconda2/envs/SNS-Analysis-py36/lib/python3.6/site-packages/matplotlib/artist.py in draw_wrapper(artist, renderer, *args, **kwargs) 48 renderer.start_filter() 49 ---> 50 return draw(artist, renderer, *args, **kwargs) 51 finally: 52 if artist.get_agg_filter() is not None:

~/anaconda2/envs/SNS-Analysis-py36/lib/python3.6/site-packages/matplotlib/figure.py in draw(self, renderer) 1647 1648 mimage._draw_list_compositing_images( -> 1649 renderer, self, artists, self.suppressComposite) 1650 1651 renderer.close_group('figure')

~/anaconda2/envs/SNS-Analysis-py36/lib/python3.6/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

~/anaconda2/envs/SNS-Analysis-py36/lib/python3.6/site-packages/matplotlib/artist.py in draw_wrapper(artist, renderer, *args, **kwargs) 48 renderer.start_filter() 49 ---> 50 return draw(artist, renderer, *args, **kwargs) 51 finally: 52 if artist.get_agg_filter() is not None:

~/anaconda2/envs/SNS-Analysis-py36/lib/python3.6/site-packages/matplotlib/axes/_base.py in draw(self, renderer, inframe) 2626 renderer.stop_rasterizing() 2627 -> 2628 mimage._draw_list_compositing_images(renderer, self, artists) 2629 2630 renderer.close_group('axes')

~/anaconda2/envs/SNS-Analysis-py36/lib/python3.6/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

~/anaconda2/envs/SNS-Analysis-py36/lib/python3.6/site-packages/matplotlib/artist.py in draw_wrapper(artist, renderer, *args, **kwargs) 48 renderer.start_filter() 49 ---> 50 return draw(artist, renderer, *args, **kwargs) 51 finally: 52 if artist.get_agg_filter() is not None:

~/anaconda2/envs/SNS-Analysis-py36/lib/python3.6/site-packages/matplotlib/lines.py in draw(self, renderer) 779 780 ec_rgba = mcolors.to_rgba( --> 781 self.get_markeredgecolor(), self._alpha) 782 fc_rgba = mcolors.to_rgba( 783 self._get_markerfacecolor(), self._alpha)

~/anaconda2/envs/SNS-Analysis-py36/lib/python3.6/site-packages/matplotlib/colors.py in to_rgba(c, alpha) 174 rgba = _colors_full_map.cache[c, alpha] 175 except (KeyError, TypeError): # Not in cache, or unhashable. --> 176 rgba = _to_rgba_no_colorcycle(c, alpha) 177 try: 178 _colors_full_map.cache[c, alpha] = rgba

~/anaconda2/envs/SNS-Analysis-py36/lib/python3.6/site-packages/matplotlib/colors.py in _to_rgba_no_colorcycle(c, alpha) 225 # float)andnp.array(...).astype(float)` all convert "0.5" to 0.5. 226 # Test dimensionality to reject single floats. --> 227 raise ValueError("Invalid RGBA argument: {!r}".format(orig_c)) 228 # Return a tuple to prevent the cached value from being modified. 229 c = tuple(c.astype(float))

ValueError: Invalid RGBA argument: ['red', 'green', 'blue']

Putting things in for loop works, but for 5000+ points, it's incredibly slow. Any suggestions?

creuzige avatar Nov 15 '19 14:11 creuzige

For what it's worth, there's nothing specific to mplstereonet in this case. It's better to back up and get a broader picture of how matplotlib handles plotting large numbers of points with different colors.

You don't typically explicitly color each point. Instead, you color points by attribute/etc (a ScalarMappable in matplotlib terms).

If you'd like to color things by some particular variable, you'd use ax.scatter. To use scatter on a stereonet, you need to work in native coordinates. There are functions to convert strikes/dips, or plunge/bearings, or rakes to native stereonet coordinates. For example:

import numpy as np
import matplotlib.pyplot as plt
import mplstereonet
np.random.seed(1)

strikes = np.arange(0, 360, 15)
dips = 45 * np.ones(strikes.size)
magnitude = np.random.random(strikes.size)

# Convert our strikes and dips to stereonet coordinates
lons, lats = mplstereonet.pole(strikes, dips)

# Now we'll plot our data and color by magnitude
fig, ax = mplstereonet.subplots()
sm = ax.scatter(lons, lats, c=magnitude, s=50, cmap='gist_earth')

ax.grid()
plt.show()

joferkington avatar Dec 31 '19 17:12 joferkington