Repository: yt-project/yt

Issue:
[bug] errors in using log normalization with large data ranges
### Bug report

This is an overview of an upstream matplotlib bug and the temporary fix going into yt to address it so that we do not forget to update yt down the line.

In the recent versions of matplotlib (not sure exactly when this appeared in the 3.3, 3.4 series) if you use a log color scaling with `imshow` and if your data range is very large you can get some unexpected behavior including crashes. This arises from some internal re-scaling that `imshow` does, resulting in rounding error when your max/min data range span many orders of magnitude. If your data also includes zeros, this can lead to the the color scale min being set to 0, which errors for log scaling, which is the source of the error in yt's issue #2890. 

The current yt fix introduced by PR #3161 is to switch to symlog scaling if you have 0s and a data range greater than 15 orders of magnitude. As the fix in #3161 is not ideal, it should be eventually removed as the fixes get merged upstream. Note that the upstream fix introduces a new boolean keyword argument, `interp_postrgba`, that yt would need to pass to its calls to `imshow`, likely with an initial matplotlib version check for some period of time (I believe these changes would be implemented in `yt.visualization.base_plot_types.ImagePlotMPL._init_image`). 

matplotlib links for tracking:
* https://github.com/matplotlib/matplotlib/issues/19748 the issue of record
* https://github.com/matplotlib/matplotlib/issues/19851 an issue I submitted before seeing 19748. Closed as a duplicate but it's still useful because it has some simpler minimal examples reproducing the bug
* https://github.com/matplotlib/matplotlib/pull/18782 the pull request (in progress as of now) that will address this issue.






Discussion:
@chrishavlin does the fix in yt-project/yt#3161 actually fix yt-project/yt#2890?
The following now runs without error on main:

```python
import yt
fn = 'FIRE_M12i_ref11/snapshot_600.hdf5'
ds = yt.load(fn)
p = yt.ProjectionPlot(ds, 'x', ('gas', 'density'))
p.save('projection.png')
```

are there more errors? 
Nope! I just want to close yt-project/yt#2890!!!
It seems like the PR addressing this upstream was merged some time ago and is currently only included in Matplotlib 3.5.0rc1, so it should land with Matplotlib 3.5.0.

Indeed https://github.com/matplotlib/matplotlib/pull/18782 was released in MPL 3.5
It'd be sufficient to make the temporary hack from #3161 version-aware (only use it with MPL < 3.5) to close the present PR, I think.

Resolving patch:
diff --git a/yt/visualization/plot_window.py b/yt/visualization/plot_window.py
--- a/yt/visualization/plot_window.py
+++ b/yt/visualization/plot_window.py
@@ -1062,7 +1062,11 @@ def _setup_plots(self):
                         f"Min = {np.nanmin(image)}, Max = {np.nanmax(image)}."
                     )
                     use_symlog = True
-                elif np.nanmax(image) > 0.0 and np.nanmin(image) == 0:
+                elif (
+                    (Version("3.3") <= MPL_VERSION < Version("3.5"))
+                    and np.nanmax(image) > 0.0
+                    and np.nanmin(image) == 0
+                ):
                     # normally, a LogNorm scaling would still be OK here because
                     # LogNorm will mask 0 values when calculating vmin. But
                     # due to a bug in matplotlib's imshow, if the data range


Test patch: