diff --git a/proplot/axes.py b/proplot/axes.py index 4eae98590..666652b51 100644 --- a/proplot/axes.py +++ b/proplot/axes.py @@ -978,6 +978,15 @@ def colorbar( self.add_child_axes(ax) # Location + # NOTE: May change loc='_fill' to 'fill' so users can manually + # fill axes but maintain proplot colorbar() features. For now + # this is just used internally by show_cmaps() and show_cycles() + if side is None: # manual + orientation = kwargs.pop('orientation', None) + if orientation == 'vertical': + side = 'left' + else: + side = 'bottom' if side in ('bottom', 'top'): outside, inside = 'bottom', 'top' if side == 'top': @@ -992,13 +1001,21 @@ def colorbar( orientation = 'vertical' # Keyword args and add as child axes - orient = kwargs.get('orientation', None) - if orient is not None and orient != orientation: - _warn_proplot(f'Overriding input orientation={orient!r}.') - ticklocation = kwargs.pop('tickloc', None) or ticklocation - ticklocation = kwargs.pop('ticklocation', None) or ticklocation - kwargs.update({'orientation': orientation, - 'ticklocation': ticklocation}) + orientation_user = kwargs.get('orientation', None) + if orientation_user and orientation_user != orientation: + _warn_proplot( + f'Overriding input orientation={orientation_user!r}.' + ) + ticklocation = _notNone( + kwargs.pop('ticklocation', None), + kwargs.pop('tickloc', None), + ticklocation, + names=('ticklocation', 'tickloc') + ) + kwargs.update({ + 'orientation': orientation, + 'ticklocation': ticklocation + }) # Inset colorbar else: diff --git a/proplot/styletools.py b/proplot/styletools.py index 60147d46f..1c469ec67 100644 --- a/proplot/styletools.py +++ b/proplot/styletools.py @@ -3194,8 +3194,6 @@ def _draw_bars(names, *, source, unknown='User', length=4.0, width=0.2): ) iax = -1 nheads = nbars = 0 # for deciding which axes to plot in - a = np.linspace(0, 1, 257).reshape(1, -1) - a = np.vstack((a, a)) for cat, names in cmapdict.items(): nheads += 1 for imap, name in enumerate(names): @@ -3207,18 +3205,16 @@ def _draw_bars(names, *, source, unknown='User', length=4.0, width=0.2): iax += 1 ax.set_visible(False) ax = axs[iax] - cmap = mcm.cmap_d[name] - ax.imshow( - a, cmap=name, origin='lower', aspect='auto', - levels=cmap.N + ax.colorbar( # TODO: support this in public API + mcm.cmap_d[name], loc='_fill', + orientation='horizontal', locator='null', linewidth=0 ) - ax.format( - ylabel=name, - ylabel_kw={'rotation': 0, 'ha': 'right', 'va': 'center'}, - xticks='none', yticks='none', # no ticks - xloc='neither', yloc='neither', # no spines - title=(cat if imap == 0 else None) + ax.text( + 0 - (rcParams['axes.labelpad'] / 72) / length, 0.45, name, + ha='right', va='center', transform='axes', ) + if imap == 0: + ax.set_title(cat) nbars += len(names) diff --git a/proplot/wrappers.py b/proplot/wrappers.py index cdef1229b..14f46cc5c 100644 --- a/proplot/wrappers.py +++ b/proplot/wrappers.py @@ -2588,7 +2588,7 @@ def colorbar_wrapper( 4. A `~matplotlib.colors.Colormap` instance. In this case, a colorbar will be drawn using this colormap and with levels determined by `values`. If `values` is ``None``, it is set to - ``np.linspace(0, 1, cmap._N)``. + ``np.linspace(0, 1, cmap.N)``. values : list of float, optional Ignored if `mappable` is a mappable object. This maps each color or @@ -2749,8 +2749,7 @@ def colorbar_wrapper( except (TypeError, KeyError): pass # List of handles - if (hasattr(obj, 'get_color') or hasattr( - obj, 'get_facecolor')): # simplest approach + if hasattr(obj, 'get_color') or hasattr(obj, 'get_facecolor'): # Make colormap colors = [] for obj in mappable: @@ -2776,21 +2775,20 @@ def colorbar_wrapper( tick_all = True # Any colormap spec, including a list of colors, colormap name, or # colormap instance - else: - try: - cmap = styletools.Colormap(mappable, listmode='listed') - except Exception: - raise ValueError( - 'Input mappable must be a matplotlib artist, ' - 'list of objects, list of colors, or colormap. ' - f'Got {mappable!r}.' - ) + elif isinstance(mappable, mcolors.Colormap): + cmap = mappable if values is None: if np.iterable(mappable) and not isinstance( mappable, str): # e.g. list of colors values = np.linspace(0, 1, len(mappable)) else: values = np.linspace(0, 1, cmap.N) + else: + raise ValueError( + 'Input mappable must be a matplotlib artist, ' + 'list of objects, list of colors, or colormap. ' + f'Got {mappable!r}.' + ) # Build new ad hoc mappable object from handles # NOTE: Need to use wrapped contourf but this might be native matplotlib