Peer Breier
Peer Breier

Reputation: 391

How to draw slope triangles in matplotlib?

What I would like to have are the triangles as shown in the image: enter image description here

Here is my code:

import matplotlib.pyplot as plt
data= [0.2855,0.3030,0.4995]
x = [1,2,3]
plt.plot(x, data)
plt.show

Is there a simple way of inserting these slope triangles as shown in the image in an automatic fashion? I would like to have the triangle in the middle between two points and with the slope written next to it.

Upvotes: 0

Views: 2208

Answers (2)

Joe Wallwork
Joe Wallwork

Reputation: 11

The triangle construction can also be done using mpltools:

import matplotlib.pyplot as plt
from mpltools import annotation
import numpy as np

data = [0.2855, 0.3030, 0.4995]
x = [1, 2, 3]

# get midpoint coordinates
x_mid = np.convolve(x, [0.5, 0.5], mode='valid')
y_mid = np.interp(x_mid, x, data)

# compute the gradient of each segment
gradients = np.diff(data)/np.diff(x)

# plot
plt.plot(x, data)
axes = plt.gca()
for xm, ym, g in zip(x_mid, y_mid, gradients):
    annotation.slope_marker((xm, ym), g)
plt.show()

The first argument of annotation.slope_marker is a tuple containing the coordinates for the left-hand corner of the triangle and the second argument is the gradient. So here we loop over the midpoints of the line segments and their gradients and annotate with a triangular slope marker for that gradient at those coordinates.

Expected Output:

Upvotes: 1

HansHirse
HansHirse

Reputation: 18895

Depending on your idea of "automatic fashion", this might be a suitable solution:

import matplotlib.pyplot as plt
import numpy as np

# Data
x = np.array([1, 2, 3])
y = np.array([0.2855, 0.3030, 0.4995])

# Calculate triangle coordinates values
x_mid = np.convolve(x, [0.5, 0.5], mode='valid')
x_tri = np.vstack((x_mid, x_mid + 0.3))
y_tri = np.interp(x_tri, x, y)

# Calculate slopes
slopes = np.diff(y) / np.diff(x)

# Plot
plt.plot(x, y)
plt.plot(x_tri, np.tile(y_tri[0, :], [2, 1]), 'r')      # red horizontal line
plt.plot(np.tile(x_tri[1, :], [2, 1]), y_tri, 'r')      # red vertical line
for i, slope in enumerate(slopes):                      # slope values
    plt.text(x_tri[1, i] + 0.05, np.mean(y_tri[:, i]), r'{0:.3f}'.format(slope))
plt.show()

Output:

Output

Put all the triangle stuff in a separate function, and it won't affect your main code too much.

Hope that helps!

Upvotes: 2

Related Questions