diff --git a/answer-store b/answer-store index 3fecf39a81..d16fa2124e 160000 --- a/answer-store +++ b/answer-store @@ -1 +1 @@ -Subproject commit 3fecf39a8166bcf328ab3852a578ad37fcc4b629 +Subproject commit d16fa2124e0a1dc95392a7e1c56db1922d39c9da diff --git a/tests/matplotlibrc b/tests/matplotlibrc index 1abfc5ef56..cafb00a02b 100644 --- a/tests/matplotlibrc +++ b/tests/matplotlibrc @@ -1,4 +1,3 @@ #### MATPLOTLIBRC FORMAT backend : Agg -mathtext.fontset : cm diff --git a/tests/tests.yaml b/tests/tests.yaml index f3c9f02899..3fdbc174ef 100644 --- a/tests/tests.yaml +++ b/tests/tests.yaml @@ -92,7 +92,7 @@ answer_tests: - yt/frontends/owls/tests/test_outputs.py:test_snapshot_033 - yt/frontends/owls/tests/test_outputs.py:test_OWLS_particlefilter - local_pw_037: # PR 3373 + local_pw_038: # PR 3520 - yt/visualization/tests/test_plotwindow.py:test_attributes - yt/visualization/tests/test_particle_plot.py:test_particle_projection_answers - yt/visualization/tests/test_particle_plot.py:test_particle_projection_filter @@ -167,7 +167,7 @@ answer_tests: local_axialpix_007: - yt/geometry/coordinates/tests/test_axial_pixelization.py:test_axial_pixelization - local_cylindrical_background_008: # PR 3536 + local_cylindrical_background_010: # PR 3520 - yt/geometry/coordinates/tests/test_cylindrical_coordinates.py:test_noise_plots #local_particle_trajectory_001: diff --git a/yt/visualization/_commons.py b/yt/visualization/_commons.py index 4f579af947..0b2b53f382 100644 --- a/yt/visualization/_commons.py +++ b/yt/visualization/_commons.py @@ -1,6 +1,9 @@ import os from typing import Optional +import matplotlib +from packaging.version import Version + from yt.utilities.logger import ytLogger as mylog from ._mpl_imports import ( @@ -10,6 +13,17 @@ FigureCanvasSVG, ) +MPL_VERSION = Version(matplotlib.__version__) + +DEFAULT_FONT_PROPERTIES = { + "family": "stixgeneral", + "size": 18, +} + +if MPL_VERSION >= Version("3.4"): + DEFAULT_FONT_PROPERTIES["math_fontfamily"] = "cm" + + AGG_FORMATS = [".png", ".jpg", ".jpeg", ".raw", ".rgba", ".tif", ".tiff"] SUPPORTED_FORMATS = AGG_FORMATS + [".eps", ".ps", ".pdf", ".svg"] diff --git a/yt/visualization/plot_container.py b/yt/visualization/plot_container.py index 062b1ed57b..7472af4c4e 100644 --- a/yt/visualization/plot_container.py +++ b/yt/visualization/plot_container.py @@ -1,13 +1,14 @@ import base64 import builtins import os +import sys import textwrap from collections import defaultdict from functools import wraps -import matplotlib import numpy as np from matplotlib.cm import get_cmap +from matplotlib.font_manager import FontProperties from more_itertools.more import always_iterable from yt._maintenance.deprecation import issue_deprecation_warning @@ -19,7 +20,7 @@ from yt.utilities.definitions import formatted_length_unit_names from yt.utilities.exceptions import YTNotInsideNotebook -from ._commons import validate_image_name +from ._commons import DEFAULT_FONT_PROPERTIES, validate_image_name try: import cmocean @@ -248,8 +249,6 @@ class PlotContainer: _units_config: dict def __init__(self, data_source, figure_size, fontsize): - from matplotlib.font_manager import FontProperties - self.data_source = data_source self.ds = data_source.ds self.ts = self._initialize_dataset(self.ds) @@ -257,10 +256,13 @@ def __init__(self, data_source, figure_size, fontsize): self.figure_size = float(figure_size[0]), float(figure_size[1]) else: self.figure_size = float(figure_size) - font_path = os.path.join( - matplotlib.get_data_path(), "fonts", "ttf", "STIXGeneral.ttf" - ) - self._font_properties = FontProperties(size=fontsize, fname=font_path) + + if sys.version_info >= (3, 9): + font_dict = DEFAULT_FONT_PROPERTIES | {"size": fontsize} + else: + font_dict = {**DEFAULT_FONT_PROPERTIES, "size": fontsize} + + self._font_properties = FontProperties(**font_dict) self._font_color = None self._xlabel = None self._ylabel = None @@ -508,7 +510,6 @@ def set_font(self, font_dict=None): ... ) """ - from matplotlib.font_manager import FontProperties if font_dict is None: font_dict = {} @@ -516,8 +517,10 @@ def set_font(self, font_dict=None): self._font_color = font_dict.pop("color") # Set default values if the user does not explicitly set them. # this prevents reverting to the matplotlib defaults. - font_dict.setdefault("family", "stixgeneral") - font_dict.setdefault("size", 18) + if sys.version_info >= (3, 9): + font_dict = DEFAULT_FONT_PROPERTIES | font_dict + else: + font_dict = {**DEFAULT_FONT_PROPERTIES, **font_dict} self._font_properties = FontProperties(**font_dict) return self diff --git a/yt/visualization/profile_plotter.py b/yt/visualization/profile_plotter.py index eddfd68fd1..ba45a06a36 100644 --- a/yt/visualization/profile_plotter.py +++ b/yt/visualization/profile_plotter.py @@ -6,6 +6,7 @@ import matplotlib import numpy as np +from matplotlib.font_manager import FontProperties from more_itertools.more import always_iterable, unzip from packaging.version import parse as parse_version @@ -17,10 +18,11 @@ from yt.utilities.logger import ytLogger as mylog from ..data_objects.selection_objects.data_selection_objects import YTSelectionContainer -from ._commons import validate_image_name +from ._commons import DEFAULT_FONT_PROPERTIES, validate_image_name from .base_plot_types import ImagePlotMPL, PlotMPL from .plot_container import ( ImagePlotContainer, + PlotContainer, get_log_minorticks, invalidate_plot, linear_transform, @@ -113,7 +115,7 @@ def data_object_or_all_data(data_source): return data_source -class ProfilePlot: +class ProfilePlot(PlotContainer): r""" Create a 1d profile plot from a data source or from a list of profile objects. @@ -374,6 +376,7 @@ def _setup_plots(self): fontproperties=self._font_properties, **self._text_kwargs[f], ) + self._set_font_properties() for i, profile in enumerate(self.profiles): for field, field_data in profile.items(): @@ -415,9 +418,7 @@ def _initialize_instance(cls, obj, profiles, labels, plot_specs, y_log): obj._text_ypos = {} obj._text_kwargs = {} - from matplotlib.font_manager import FontProperties - - obj._font_properties = FontProperties(family="stixgeneral", size=18) + obj._font_properties = FontProperties(**DEFAULT_FONT_PROPERTIES) obj._font_color = None obj.profiles = list(always_iterable(profiles)) obj.x_log = None @@ -1336,77 +1337,6 @@ def save(self, name=None, suffix=".png", mpl_kwargs=None): self.plots[f].save(name, mpl_kwargs) return names - @invalidate_plot - def set_font(self, font_dict=None): - """ - - Set the font and font properties. - - Parameters - ---------- - - font_dict : dict - A dict of keyword parameters to be passed to - :class:`matplotlib.font_manager.FontProperties`. - - Possible keys include: - - * family - The font family. Can be serif, sans-serif, cursive, - 'fantasy', or 'monospace'. - * style - The font style. Either normal, italic or oblique. - * color - A valid color string like 'r', 'g', 'red', 'cobalt', - and 'orange'. - * variant - Either normal or small-caps. - * size - Either a relative value of xx-small, x-small, small, - medium, large, x-large, xx-large or an absolute font size, e.g. 12 - * stretch - A numeric value in the range 0-1000 or one of - ultra-condensed, extra-condensed, condensed, semi-condensed, - normal, semi-expanded, expanded, extra-expanded or ultra-expanded - * weight - A numeric value in the range 0-1000 or one of ultralight, - light, normal, regular, book, medium, roman, semibold, demibold, - demi, bold, heavy, extra bold, or black - - See the matplotlib font manager API documentation for more details. - https://matplotlib.org/stable/api/font_manager_api.html - - Notes - ----- - - Mathtext axis labels will only obey the `size` and `color` keyword. - - Examples - -------- - - This sets the font to be 24-pt, blue, sans-serif, italic, and - bold-face. - - >>> prof = ProfilePlot( - ... ds.all_data(), ("gas", "density"), ("gas", "temperature") - ... ) - >>> slc.set_font( - ... { - ... "family": "sans-serif", - ... "style": "italic", - ... "weight": "bold", - ... "size": 24, - ... "color": "blue", - ... } - ... ) - - """ - from matplotlib.font_manager import FontProperties - - if font_dict is None: - font_dict = {} - if "color" in font_dict: - self._font_color = font_dict.pop("color") - # Set default values if the user does not explicitly set them. - # this prevents reverting to the matplotlib defaults. - font_dict.setdefault("family", "stixgeneral") - font_dict.setdefault("size", 18) - self._font_properties = FontProperties(**font_dict) - return self - @invalidate_plot def set_title(self, field, title): """Set a title for the plot.