1

Is it possible, when plotting an n-dimensional unstructured array with matplotlib, to produce a legend label for each dimension?

  • The solution of a system of ODEs, when using scipy.integrate.odeint, is returned as an array of shape (100, 5) for 5 variables.
  • I want to plot the solution from one system as lines, so plt.plot(sol, '-'), reset the color cycle, then plot the same 5 again calculated using another ODE system, using plt.plot(sol_estimate, '--').
  • This way, I have the 5 variables in one plot, the exact, as lines, and the approximate, as dashes.
  • I can try to play with the opacity later in case the solutions are hard to differentiate
  • The primary objective is to get the legend for the 10 lines in an easy way.
  • Best would be some loop since we can call them u1, u2, u3, u4, u5, u1_e, u2_e, u3_e, u4_e, u5_e.
  • Is this possible in matplotlib?
0

1 Answer 1

1
  • This example only uses a second order ODE, but should get the idea across for how to add a legend.
  • Convert the unstructured array into a structured array, by adding dtype to the sol array.
from scipy.integrate import odeint
import numpy as np
import matplotlib.pyplot as plt


# ode system
def pend(y, t, b, c):
    theta, omega = y
    dydt = [omega, -b*omega - c*np.sin(theta)]
    return dydt

b = np.arange(0.50, 0, -0.25)
c = 5.0
y0 = [np.pi - 0.1, 0.0]
t = np.linspace(0, 10, 101)

ls = ['-', '--']  # list of linestyles
count = 0  # used to index the current linestyle
for i in b:
    
    sol = odeint(pend, y0, t, args=(i, c))

    type_to_set = 'float64'  # specify the type you need (e.g. 'float64')
    dtype = np.dtype([(f'{x}_ode:{i}', type_to_set) for x in range(sol.shape[1])])  # create names and dtypes list
    sol_updated = sol.astype(type_to_set).view(dtype)  # add names and dtypes to sol
    
    # plot
    # plt.figure()  # if you want separate plots for each group uncomment this line & put plt.legend in 4 spaces, so it's just after the plotting loop
    for name in sol_updated.dtype.names:
        plt.plot(t, sol_updated[name], linestyle=ls[count], label=name)

    count += 1  # add 1 to the markers indexer
    plt.gca().set_prop_cycle(None)

plt.legend(bbox_to_anchor=(1.04, 0.5), loc='center left', borderaxespad=0)
plt.show()
  • This is 2 sets of (101, 2) arrays on the same plot with unique line styles for each ode solution group.

enter image description here

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

1 Comment

Thanks a lot. I just had to add a plt.gca().set_prop_cycle(None) at the end of the outer for loop and it met all my criteria since I wanted to have the estimates and originals in the same color, just one as solid line and one as dashed.

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.