3

I currently have my problem solved using the code block below. It does what I want, however there is a lot of code duplication and it is a bit hard to read.

I have several figures I would like to create and populate with data that is calculated in a large for loop.

I am having trouble figuring out the syntax to create and set the titles/meta data at the top of my code, and then add all the proper data to the correct figures in the bottom of my code.

I have this:

import matplotlib.pyplot as plt
import numpy as np
figure = plt.figure()
plt.title("Figure 1")
figure.add_subplot(2,2,1)
plt.imshow(np.zeros((2,2)))
# Some logic in a for loop to add subplots
plt.show()

figure = plt.figure()
plt.title("Figure 2")
figure.add_subplot(2,2,1)
# Some Logic in an identical for loop to add different subplots
plt.imshow(np.zeros((2,2)))
plt.show()

I want something that looks more like this:

# Define variables, titles, formatting, etc.
figure = plt.figure()
figure2 = plt.figure()
figure1.title = "Figure 1"
figure2.title = "Figure 2"

# Populate
figure.add_subplot(2,2,1)
figure2.add_subplot(2,2,1)
# Some logic in a for loop to add subplots to both figures

Is there a clean way to do what I am asking with matplotlib? I am mostly looking to cleanup my code a bit and have a program that is easier to expand and maintain.

I really just want a way to define all my figures and there titles in one place and then add images to the correct figure depending on some other logic. Being able to call plt.show() for a specific figure would also be good.

2 Answers 2

1

In order to manipulate different figures at different points in the code, it's easiest to keep a reference to all of them. Also keeping a reference to the respective axes is useful to be able to plot to them.

import matplotlib.pyplot as plt

figure = plt.figure(1)
figure2 = plt.figure(2)
figure.title("Figure 1")
figure2.title("Figure 2")

ax1 = figure.add_subplot(2,2,1)
ax2 = figure2.add_subplot(2,2,1)
ax999 = figure2.add_subplot(2,2,4)

ax1.plot([2,4,1])
ax2.plot([3,0,3])
ax999.plot([2,3,1])

plt.show()

plt.show() should always be called at the end. It will then plot all open figures. To only show some of the figures, one would need to write a custom show function. This function simply closes all unwanted figures before calling plt.show.

import matplotlib.pyplot as plt

def show(fignums):
    if isinstance(fignums, int):
        fignums = [fignums]
    allfigs = plt.get_fignums()
    for f in allfigs:
        if f not in fignums:
            plt.close(f)
    plt.show()


figure = plt.figure(1)
figure2 = plt.figure(2)
figure.title("Figure 1")
figure2.title("Figure 2")

ax1 = figure.add_subplot(2,2,1)
ax2 = figure2.add_subplot(2,2,1)

ax1.plot([2,4,1])
ax2.plot([3,0,3])

show([1, 2])

Possible (mutually exclusive) ways to call show would now be

show(1) # only show figure 1
show(2) # only show figure 2
show([1,2]) # show both figures
show([]) # don't show any figure

Note that you still can call show only once at the end of the script.

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

Comments

1

Put your figures to a list and navigate over them by it number:

import matplotlib.pyplot as plt
import numpy as np

# data
t = np.arange(0.0, 2.0, 0.01)
s1 = np.sin(2*np.pi*t)
s2 = np.sin(4*np.pi*t)

# set up figures
figures = []
for ind in xrange(1,4):
   f = plt.figure()
   figures.append(f) 
   f.title = "Figure {0:02d}".format(ind)

# Populate with subplots
figures[0].add_subplot(2,2,1)
figures[1].add_subplot(2,2,1)

# select first figure
plt.figure(1) 
# get current axis
ax = plt.gca()
ax.plot(t, s2, 's')

# select 3rd figure
plt.figure(3) 
ax = plt.gca()
ax.plot(t, s1, 's')

plt.show()

If you need you may plot in first cycle. To close figure use plt.close(figures[0])

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.