9

Is there a way to either specify different alphas for facecolor vs edgecolor? Or is there a way to plot an alpha filled area with non-alpha edgecolor that also works in the legend?

This is not what I want... enter image description here

axs.fill_between(xvalues, tupper_w, tlower_w, facecolor='dimgray', edgecolor='dimgray', alpha=0.25, label='$measured\quad\sigma$')
axs.fill_between(xvalues, pupper_w, plower_w, facecolor='orange', edgecolor='orange', alpha=0.25, label='$predicted\quad\sigma$')
axs.plot(xvalues, tcurvesavg_w, color='dimgray', label='$\overline{measured}$', ls='--')
axs.plot(xvalues, pcurvesavg_w, color='orange', label='$\overline{predicted}$', ls='--')


This is what I want (but with proper legend): enter image description here

axs.fill_between(xvalues, tupper, tlower, facecolor='dimgray', alpha=0.25, label='$measured\quad\sigma$')
axs.fill_between(xvalues, pupper, plower, facecolor='orange', alpha=0.25, label='$predicted\quad\sigma$')
axs.plot(xvalues, tupper, color='dimgray', lw=0.5)
axs.plot(xvalues, tcurvesavg, color='dimgray', label='$\overline{measured}$', ls='--')
axs.plot(xvalues, tlower, color='dimgray', lw=0.5)
axs.plot(xvalues, pupper, color='orange', lw=0.5)
axs.plot(xvalues, pcurvesavg, color='orange', label='$\overline{predicted}$', ls='--')
axs.plot(xvalues, plower, color='orange', lw=0.5)
delrocco
  • 495
  • 1
  • 4
  • 23

2 Answers2

13

You cannot specify different alpha values via the alpha argument. However you can define each of facecolor and edgecolor with an alpha channel, e.g. for red with 40% opacity

facecolor=(1,0,0,.4)

This is then directly applied in the legend.

import matplotlib.pyplot as plt
import numpy as np

x = np.arange(0.0, 2, 0.01)
y1 = np.sin(2*np.pi*x)
y2 = 1.2*np.sin(4*np.pi*x)-.9

fig, ax = plt.subplots()

ax.fill_between(x, y1, y1+.5, facecolor=(1,0,0,.4), edgecolor=(0,0,0,.5), label="Label 1")
ax.fill_between(x, y2, y2-.5, facecolor=(0,0,1,.4), edgecolor=(0,0,0,.5), label="Label 1")

ax.legend()
plt.show()

enter image description here

ImportanceOfBeingErnest
  • 321,279
  • 53
  • 665
  • 712
1

Immediately, looking at fill_between alpha and general fill_between documentation it appears to be unsupported. The legend documentation doesn't seem to provide an option for adding your border after plotting either.

In your second code snippet, if you can figure out how to get the plot and fill functions to have a single handle then the legend should automatically format. Something similar to below (adapted from this similar, but not quite duplicate StackExchangePost):

import matplotlib.patches as mpatches
import matplotlib.pyplot as plt
import numpy as np

xvalues = np.linspace(0,1,11)
tcurvesavg = np.linspace(0,1,11)
p1, = plt.plot(xvalues, tcurvesavg , c='r')  # notice the comma!
p2 = plt.fill_between(xvalues, tcurvesavg -0.2, tcurvesavg +0.2, color='r', alpha=0.5)
plt.legend(((p1,p2),), ('Entry',))
plt.show()

(As a non-automated workaround for most matplotlib questions, save as a svg (similar to this post) and add a border in a vector graphics program like Inkscape. You shouldn't lose resolution, and could still put it in reports etc.)

  • I will try that, thx! And yea, I was going to post-process the final ones if no procedural solution could be found. I'm generating hundreds of different plots across all my experiments, so I was trying to make sure it worked from the start. But post-process is necessary sometimes :/ – delrocco Jul 24 '18 at 18:21
  • 1
    @delrocco *TheImportanceOfBeingErnest*'s answer absolutely does what you are looking for, you should mark it as accepted. – Guimoute Jan 29 '20 at 15:42