2
  • I would like to define a standard matplotlib style using a matplotlibrc file, with the plot legend outside the plot. This is possible using bbox_to_anchor in the plot code, but this is not a known rcparam. Any other options?

  • Is it possible to make all plot titles appear in capitals using matplotlibrc?

Karen
  • 47
  • 4
  • The [answer here](https://stackoverflow.com/questions/3439344/setting-spines-in-matplotlibrc) seems useful for figuring out what can be controlled by matplotlibrc and what can't. I haven't checked for bbox_to_anchor and uppercasing, though. – cphlewis Jan 24 '22 at 19:42
  • If the answer without bbox_to_anchor was useful, this question might be more useful with a different title. "Automatically plot with a legend outside the plot"? "Enforcing plot styles without rcParams"? – cphlewis Feb 01 '22 at 01:35

1 Answers1

2

Short answer is that neither of those things can be set in rcParams. You can get the sidebar-legend by passing a tuple as the loc argument to legend(), but rcParams can't handle tuple values yet. And I don't think rcParams is the right place to do text modification like uppercasing.

You can put both into a decorator, along with rcParams, and have a decorated version of pyplot calls:


import matplotlib.pyplot as plt
import matplotlib as mpl

xs, x2s, ys = [4,1,3,5,2], [1,2,3,4,5], [2,3,1,2,-1]

def house_style(func):
    def sidelegend_wrapper(*args, **kwargs):
        title = kwargs.pop('title', None)
        with plt.style.context('dark_background'): #or your rcParams
            func(*args, **kwargs)
            cf = plt.gcf()
            cf.subplots_adjust(right=0.7)
            cax = plt.gca()
            if title: cax.set_title(title.upper())
            cax.legend(loc=(1.1, .8))
    return(sidelegend_wrapper)

@house_style
def decorated_scatter(*args, **kwargs):
    plt.scatter(*args, **kwargs)

@house_style
def decorated_plot(*args, **kwargs):
    plt.plot(*args, **kwargs)
    
decorated_scatter(xs, ys, label='decorator', title='lowercase')
decorated_plot(x2s, ys, label='also dec')

Result:

Plot with dark background from rcParam stylesheet, side legend from decorator

If I needed to plot into specific axes instead of using pyplot I would put that and what just went into the decorator into a function:


def our_function(*args, **kwargs):
    title = kwargs.pop('title', None)
    sc_data = kwargs.pop('sc_data', None)
    line_data = kwargs.pop('line_data', None)
    fig, axs= plt.subplots(2)
    fig.subplots_adjust(right=0.7)
    axs[0].scatter(sc_data[0],sc_data[1], **kwargs)
    axs[1].plot(line_data[0], line_data[1], **kwargs)
    if title: fig.suptitle(title.upper())
    axs[0].legend(loc=(1.1,.5))

  

our_function(sc_data = [xs, ys], line_data=[x2s, ys], label='function', title='lowercase\nwell, it was')

plt.show()

two-axes plot with capitalized title and side legend

That one doesn't call rcParams but could, just like the decorators.

Possibly one could decorate the Axes class itself so that every instance had decorated plotting functions?

cphlewis
  • 15,759
  • 4
  • 46
  • 55