Repository: yt-project/yt

Issue:
Can't generate multipanel plot with PhasePlot
### Bug report

**Bug summary**

A multipanel plot with PhasePlot can not be generated normally following the guidance in the cookbook unless using `annotate_title` to add a title. 

**Code for reproduction**

A minimum reproducible example is listed below. This example can not generate a mutlipanel phase plot normally (shown in _Actual outcome_ ). However, if the line `phs.annotate_title(title)` hasn't been commented out, the plot will be created correctly  (shown in _Expected outcome_ ).

```python
import matplotlib.pyplot as plt
from mpl_toolkits.axes_grid1 import AxesGrid
from yt.testing import fake_amr_ds
import yt

fig = plt.figure()
grid = AxesGrid(
fig,
111,
nrows_ncols=(2, 2),
axes_pad=0,
label_mode="L",
share_all=True,
cbar_location="right",
cbar_mode="single",
cbar_size="3%",
cbar_pad="0%",
aspect=True )
for i,title in enumerate(["995","1133","37373","37548"]):
    ds = fake_amr_ds()
    phs = yt.PhasePlot(ds,("gas","x"),("gas","y"),("gas","volume"),weight_field=None)
    # phs.annotate_title(title) # the multipanel plot can't be generated if this line has been commented out.
    plot = phs.plots[("gas","volume")]
    plot.figure = fig
    plot.axes = grid[i].axes
    if i == 0:
        plot.cax = grid.cbar_axes[i]
    phs.render()
plt.savefig("test.jpg")
```

**Actual outcome**

![abnormal](https://github.com/yt-project/yt/assets/64591250/e344f8da-cdfa-490e-b428-078cefbaf1fc)

**Expected outcome**

![normal](https://github.com/yt-project/yt/assets/64591250/b0f5a43b-c13d-4f61-82c8-854e57c26965)

**Version Information**

  * Operating System: WSL2 (Ubuntu-20.04)
  * Python Version: 3.8.10
  * yt version: 4.3.dev0
  * Other Libraries (if applicable): matplotlib: 3.6.2



Discussion:
Hi, and welcome to yt!  Thanks for opening your first issue.  We have an issue template that helps us to gather relevant information to help diagnosing and fixing the issue.

wow, that's a weird one !
An interesting consequence of the current behaviour is that the title-less version of the multi-panel figure may be obtained by calling `phs.annotate_title("")`.

Thank you for reporting and providing a nice, self-contained and minimal reproducer ! I'll look into it now.
So, it's actually not something weird going on with `annotate_title` specifically: any plot annotation has a similar effect here. What they all have in common is that they *invalidate the plot object*: they force a new rendering next time the figure needs to be displayed.
In fact, replacing `psh.annotate_title("")` with `phs._plot_valid = False` also produces the correct result.
I also note that if I replace the phase plot with a slice plot, `_plot_valid` is `False` from the start (no annotation needed), so the end result is correct.
This seems to indicate that the attribute `_plot_valid` is improperly initialised to `True` in `PhasePlot`.

Resolving patch:
diff --git a/yt/visualization/profile_plotter.py b/yt/visualization/profile_plotter.py
--- a/yt/visualization/profile_plotter.py
+++ b/yt/visualization/profile_plotter.py
@@ -259,6 +259,7 @@ def _initialize_instance(
         obj.plot_spec = plot_specs
         obj._xlim = (None, None)
         obj._setup_plots()
+        obj._plot_valid = False  # see https://github.com/yt-project/yt/issues/4489
         return obj
 
     def _get_axrect(self):
@@ -977,6 +978,7 @@ def _initialize_instance(
         obj._ylim = (None, None)
         super(PhasePlot, obj).__init__(data_source, figure_size, fontsize)
         obj._setup_plots()
+        obj._plot_valid = False  # see https://github.com/yt-project/yt/issues/4489
         obj._initfinished = True
         return obj
 


Test patch: