1

I want to generate a figure inside a function, and then be able to add additional stuff to that plot in another function. I would like both figures (the original and the edited one) to be available for future usage. Something like:

import numpy as np
import matplotlib.pyplot as plt

def plot_1():
    X, Y = np.meshgrid(np.linspace(0, 10, 100), np.linspace(0, 10, 50))
    z = np.random.rand(50, 100)

    fig, ax = plt.subplots()
    ax.contourf(X, Y, z, cmap="viridis")

    return fig

def plot_2(fig):
    ax = fig.axes[0]
    ax.scatter([2, 5], [1, 4], zorder=2.5, color="r")

    return ax

f = plot_1()
f2 = plot_2(f)

However, this changes the original image (which I would like to stay as it originally was) and doesn't return a printable figure in f2. At first I thought the problem was that the scatter plot was not being done but as suggested by Lucas in the comments that was not the actual issue, as it could be solved with a correct value for zorder.

How can I get this right?

Tendero
  • 1,136
  • 2
  • 19
  • 34
  • The problem is the order of the plot. By default the scatter is it is below the other plot. (For example, if you make two scatters with different values, you will see that your code works perfectly). Try with: `ax.scatter([2, 5], [1, 4], zorder=2.5)` – Lucas May 07 '21 at 03:20
  • Does this answer your question? [Matplotlib: Scatter Plot to Foreground on top of a Contour Plot](https://stackoverflow.com/questions/17431441/matplotlib-scatter-plot-to-foreground-on-top-of-a-contour-plot) – Lucas May 07 '21 at 03:20
  • @Lucas That seems to solve part of the problem, but the script doesn't still behave as I want it to. Namely, I need `f` and `f2` to be different figures that can be used/shown independently when needed. In the code as it is, it appears that the first figure is being changed and the 2nd figure isn't even a figure. Is there a way to solve that? I've edited the question to make my problem clearer. – Tendero May 07 '21 at 13:01

1 Answers1

1

If I understand correctly: you want to have two figures, plot the same in both and then only in one make some extra plots.

The way to do this is to create the figures outside the functions and pass the axes to the functions:

import numpy as np
import matplotlib.pyplot as plt

def plot_1(ax):
    X, Y = np.meshgrid(np.linspace(0, 10, 100), np.linspace(0, 10, 50))
    z = np.random.rand(50, 100)
    ax.contourf(X, Y, z, cmap="viridis")

def plot_2(ax):
    ax.scatter([2, 5], [1, 4], zorder=2.5, color="r")


fig_1, ax_1 = plt.subplots()
fig_2, ax_2 = plt.subplots()

plot_1(ax_1)
plot_1(ax_2)
plot_2(ax_2)

This will plot the two figures with the contourf but only one with the scatter.

Lucas
  • 6,869
  • 5
  • 29
  • 44
  • Hi Lucas, thanks for your answer. However, it doesn't solve my original question. I need to plot the first figure *once*, as doing it requires some heavy computation in my real case. That's why I just want to be able to copy it and edit it in another function, instead of creating it again from scratch. Am I making myself clear? Maybe I am not being able to convey my issue properly... – Tendero May 07 '21 at 16:59
  • I don't think it is possible to copy (or deepcopy) the fig ( look at [this answer](https://stackoverflow.com/a/15963012/3954379) ). If the heavy computation is before the plot (and not the plot itself) you can cache those results and reuse them later. If plot is the problem maybe you can do something like [this](https://stackoverflow.com/a/45812071/3954379) – Lucas May 07 '21 at 17:08