3

I'm using matplotlib for work and company policy is to include a watermark on every plot we make. Is there a way to set matplotlib to do this by default?

I'm currently passing each Axes object into a helper function which adds the watermark in the bottom left corner.

import matplotlib.pyplot as plt

def add_watermark(ax):
    ax.text(ax.get_xlim()[0] + 0.1, 
            ax.get_ylim()[0] + 0.1, 
            "<Company Name>", 
            alpha=0.5)

fig, ax = plt.subplots(1, 1)
x = np.fromiter((np.random.uniform() for _ in range(100)), dtype=np.float32)
y = np.fromiter((np.random.uniform() for _ in range(100)), dtype=np.float32)
ax.scatter(x, y)
add_watermark(ax)

I would like to modify the default behavior of matplotlib so that I don't have to pass each axes instance into a helper function.

1
  • if you are feeling adventurous, I suppose you can monkey-patch the constructor of the axes to include the watermark? Commented Jul 11, 2019 at 4:40

3 Answers 3

4

You may easily subclass and monkey-patch the default axes. So create a file matplotlib_company.py like this

import matplotlib.axes
from matplotlib.offsetbox import AnchoredText

class MyAxes(matplotlib.axes.Axes):
    def __init__(self, *args, **kwargs):

        super().__init__(*args, **kwargs)
        ab = AnchoredText("<company name>", loc="lower left", frameon=False,
                          borderpad=0, prop=dict(alpha=0.5))
        ab.set_zorder(0)
        self.add_artist(ab)

matplotlib.axes.Axes = MyAxes

Then import it everywhere you need it. I.e. the following

import matplotlib_company
import matplotlib.pyplot as plt
plt.plot([1,2,3])
plt.show()

creates

enter image description here

Sign up to request clarification or add additional context in comments.

1 Comment

As of matplotlib version 3.6.2, your code does not work. Any plot including an legend will fail and plots without a legend have no <company name> printed.
1

I think the cleanest solution for this is to create a "company plot template" within a separate python script (e.g. called companyplots.py) that's somewhere within python's module search path.

You can do this either by simply having it in the same folder as your actual plots, or e.g. by creating a /some/path/to/user_modules folder and correctly setting the $PYTHONPATH variable to include the path to it.

Within this file, collect all necessary imports and setup a function with default plot settings, e.g.:

def companyFigure((rows,cols),(width,height)=(768,576),dpi=72,fig_kwargs={}):
    """
    first, reset mpl style to default, then enforce a new one. 
    This is helpful when the new style does not overwrite *all* attributes 
    """
    style="ggplot" ##<- put your own style file here, if you have one
    mpl.rcParams.update(mpl.rcParamsDefault)
    mpl.style.use(style)

    ## that's your function:
    def add_watermark(ax):
        ax.text(ax.get_xlim()[0] + 0.1, 
                ax.get_ylim()[0] + 0.1, 
                "<Company Name>", 
                alpha=0.5)

    ## create figure with some arguments
    fig,ax=plt.subplots(rows,cols,
            figsize=(width/float(dpi),height/float(dpi)),
            dpi=dpi,
            **fig_kwargs
            )

    ## I'm presuming that you may want to have subplots somewhere down the line;
    ## for the sake of consistency, I'm thus making sure that "ax" is always a dict:
    if rows==1 and cols==1:
        ax={0:ax}

    for a in ax:
        add_watermark(a)

    return fig,ax

Now, all future plots can fall back to this template, simply by running:

from companyplots import *

fig,ax=companyFigure((2,1),(500,300))
## do your plotting here...
plt.show()

Comments

0

Since Matplotlib version 3.6 and Seaborn 0.12, I use:

def addwatermark(ax):
    """ Place watermark in bottom right of figure. """
    text = "<watermark>"
    ax.annotate(text, xy=(0.3, 0.1), xycoords='axes fraction', alpha=0.4, fontsize='large', rotation=45, fontweight=550)

You can add this in a separate addwatermark.py file and call from addwatermark.py import addwatermark.

Usage example:

import matplotlib.pyplot as plt
from addwatermark.py import addwatermark

fig, ax = plt.subplots()
ax.plot(x=[1, 2, 3, 4, 5], y=[1, 2, 3, 4, 5])
addwatermark(ax)
plt.show()

Also Seaborn works:

import seaborn as sns
import matplotlib.pyplot as plt
from addwatermark.py import addwatermark
ax = sns.scatterplot(x=[1, 2, 3, 4, 5], y=[1, 2, 3, 4, 5])
addwatermark(ax)
plt.show()

If you use facetgrid or pairgrid in Seaborn, the axes can be accessed through their attribute ax.

Matplotlib also has an example, but that did not work with Seaborn.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.