gota
gota

Reputation: 2649

Line plot that continuously varies transparency - Matplotlib

I wish to produce a single line plot in Matplotlib that has variable transparency, i.e. it starts from solid color to full transparent color.

I tried this but it didn't work.

import numpy as np
import matplotlib.pyplot as plt

x = np.linspace(0, 2 * np.pi, 500)
y = np.sin(x)
alphas = np.linspace(1, 0, 500)
fig, ax = plt.subplots(1, 1)
ax.plot(x, y, alpha=alphas)

Upvotes: 2

Views: 2513

Answers (3)

Dave Rove
Dave Rove

Reputation: 953

Matplotlib's "LineCollection" allows you to split the line to be plotted into individual line segments and you can assign a color to each segment. The code example below shows how each horizontal "x" value can be assigned an alpha (transparency) value that indexes into a sequential colormap that runs from transparent to a given color. A suitable colormap "myred" was created using Matplotlib's "colors" module.

import numpy as np
import matplotlib.pyplot as plt
from matplotlib.collections import LineCollection
import matplotlib.colors as colors

redfade = colors.to_rgb("red") + (0.0,)
myred = colors.LinearSegmentedColormap.from_list('my',[redfade, "red"])

x    = np.linspace(0,1, 1000)
y    = np.sin(x * 4 * np.pi)
alphas = x * 4 % 1

points = np.vstack((x, y)).T.reshape(-1, 1, 2)
segments = np.hstack((points[:-1], points[1:]))

fig, ax = plt.subplots()
lc = LineCollection(segments, array=alphas, cmap=myred, lw=3)
line = ax.add_collection(lc)
ax.autoscale()
plt.show()

Line plot that continuously varies transparency - Matplotlib

If you are using the standard white background then you can save a few lines by using one of Matplotlib's builtin sequential colormaps that runs from white to a given color. If you remove the lines that created the colormap above and just put the agument cmap="Reds" in the LineCollection function, it creates a visually similar result.

Upvotes: 4

foglerit
foglerit

Reputation: 8269

I don't know how to do this in matplotlib, but it's possible in Altair:

import numpy as np
import pandas as pd
import altair as alt
x = np.linspace(0, 2 * np.pi, 500)
y = np.sin(x)
alt.Chart(
    pd.DataFrame({"x": x, "y": y, "o": np.linspace(0, 1, len(x))}),
).mark_point(
).encode(
    alt.X("x"),
    alt.Y("y"),
    alt.Opacity(field="x", type="quantitative", scale=alt.Scale(range=[1, 0]), legend=None),
)

Result: enter image description here

Upvotes: 1

gota
gota

Reputation: 2649

The only solution I found was to plot each segment independently with varying transparency

import numpy as np
import matplotlib.pyplot as plt

x = np.linspace(0, 2 * np.pi, 500)
y = np.sin(x)
alphas = np.linspace(1, 0, 499)
fig, ax = plt.subplots(1, 1)
for i in range(499):
    ax.plot(x[i:i+2], y[i:i+2], 'k', alpha=alphas[i])

But I don't like it... Maybe this is enough for someone

Upvotes: 1

Related Questions