Coverage for pySDC/helpers/plot_helper.py: 94%
33 statements
« prev ^ index » next coverage.py v7.16.2, created at 2026-10-15 10:50 +0000
« prev ^ index » next coverage.py v7.16.2, created at 2026-10-15 10:50 +0000
1import matplotlib as mpl
2import matplotlib.pyplot as plt
3import shutil
5default_mpl_params = mpl.rcParams.copy()
8def figsize(textwidth, scale, ratio):
9 """
10 Get figsize.
12 Args:
13 textwidth (str): Textwdith in your LaTeX file in points
14 scale (float): The width of the figure relative to the textwidth
15 ratio (float): The height of the figure relative to its width
17 Returns:
18 list: Width and height of the figure to be passed to matplotlib
19 """
20 fig_width_pt = textwidth # Get this from LaTeX using \the\textwidth
21 inches_per_pt = 1.0 / 72.27 # Convert pt to inch
22 fig_width = fig_width_pt * inches_per_pt * scale # width in inches
23 fig_height = fig_width * ratio # height in inches
24 fig_size = [fig_width, fig_height]
25 return fig_size
28def figsize_by_journal(journal, scale, ratio): # pragma: no cover
29 """
30 Get figsize for specific journal. If you supply a text height, we will rescale the figure to fit on the page instead
31 of the parameters supplied.
33 Args:
34 journal (str): Name of journal
35 scale (float): The width of the figure relative to the textwidth
36 ratio (float): The height of the figure relative to its width
38 Returns:
39 list: Width and height of the figure to be passed to matplotlib
40 """
41 # store text width in points here, get this from LaTeX using \the\textwidth
42 textwidths = {
43 'JSC_beamer': 426.79135,
44 'Springer_Numerical_Algorithms': 338.58778,
45 'Springer_proceedings': 347.12354,
46 'JSC_thesis': 434.26027,
47 'TUHH_thesis': 426.79135,
48 'Nature_CS': 372.0,
49 'CPC': 468.3324,
50 }
51 # store text height in points here, get this from LaTeX using \the\textheight
52 textheights = {
53 'JSC_beamer': 214.43411,
54 'JSC_thesis': 635.5,
55 'TUHH_thesis': 631.65118,
56 'Springer_proceedings': 549.13828,
57 'Nature_CS': 552.69478,
58 'CPC': 637.31475,
59 }
60 assert (
61 journal in textwidths.keys()
62 ), f"Textwidth only available for {list(textwidths.keys())}. Please implement one for \"{journal}\"! Get the textwidth using \"\\the\\textwidth\" in your tex file."
64 # see if the figure fits on the page or if we need to apply the scaling to the height instead
65 if scale * ratio * textwidths[journal] > textheights.get(journal, 1e9):
66 if textheights[journal] / scale / ratio > textwidths[journal]:
67 raise ValueError(
68 f"We cannot fit figure with scale {scale:.2f} and ratio {ratio:.2f} on the page for journal {journal}!"
69 )
70 return figsize(textheights[journal] / (scale * ratio), 1, ratio)
72 return figsize(textwidths[journal], scale, ratio)
75def setup_mpl(font_size=8, reset=False):
76 """
77 Set the matplotlib rcParams for publication plots, with LaTeX for text if `latex` is found, and close all figures.
79 Args:
80 font_size (int): Font size in points
81 reset (bool): Restore the rcParams from import time before applying the style
83 Returns:
84 None
85 """
86 if reset:
87 mpl.rcParams.update(default_mpl_params)
89 # Set up plotting parameters
90 style_options = { # setup matplotlib to use latex for output
91 "font.family": "serif",
92 "font.serif": [], # blank entries should cause plots to inherit fonts from the document
93 "font.sans-serif": [],
94 "font.monospace": [],
95 # "axes.labelsize": 8, # LaTeX default is 10pt font.
96 "axes.linewidth": 0.5,
97 "font.size": font_size,
98 # "legend.fontsize": 6, # Make the legend/label fonts a little smaller
99 "legend.numpoints": 1,
100 # "xtick.labelsize": 6,
101 "xtick.major.width": 0.5, # major tick width in points
102 "xtick.minor.width": 0.25,
103 # "ytick.labelsize": 6,
104 "ytick.major.width": 0.5, # major tick width in points
105 "ytick.minor.width": 0.25,
106 "lines.markersize": 4,
107 "lines.markeredgewidth": 0.5,
108 "grid.linewidth": 0.5,
109 "grid.linestyle": '-',
110 "grid.alpha": 0.25,
111 "figure.subplot.hspace": 0.0,
112 "savefig.pad_inches": 0.01,
113 }
115 mpl.rcParams.update(style_options)
117 if shutil.which('latex'):
118 latex_support = {
119 "pgf.texsystem": "pdflatex", # change this if using xetex or lautex
120 "text.usetex": True, # use LaTeX to write all text
121 "pgf.preamble": r"\usepackage[utf8x]{inputenc}"
122 r"\usepackage[T1]{fontenc}"
123 r"\usepackage{underscore}"
124 r"\usepackage{amsmath,amssymb,marvosym}",
125 }
126 else:
127 latex_support = {
128 "text.usetex": False, # use LaTeX to write all text
129 }
131 mpl.rcParams.update(latex_support)
132 plt.close('all')
135def newfig(textwidth, scale, ratio=0.6180339887):
136 """
137 Clear the current figure and create a new figure with one axis, sized with `figsize`.
139 Args:
140 textwidth (float): Textwidth in your LaTeX file in points
141 scale (float): The width of the figure relative to the textwidth
142 ratio (float): The height of the figure relative to its width
144 Returns:
145 matplotlib.figure.Figure: The figure
146 matplotlib.axes.Axes: The axis
147 """
148 plt.clf()
149 fig, ax = plt.subplots(figsize=figsize(textwidth, scale, ratio))
150 return fig, ax
153def savefig(filename, save_pdf=True, save_pgf=True, save_png=True):
154 """
155 Save the current figure with a tight bounding box in the chosen formats, then close it.
157 Args:
158 filename (str): Path without extension, which is added for each format
159 save_pdf (bool): Save as pdf
160 save_pgf (bool): Save as pgf, only done if `latex` is found
161 save_png (bool): Save as png
163 Returns:
164 None
165 """
166 if save_pgf and shutil.which('latex'):
167 plt.savefig('{}.pgf'.format(filename), bbox_inches='tight')
168 if save_pdf:
169 plt.savefig('{}.pdf'.format(filename), bbox_inches='tight')
170 if save_png:
171 plt.savefig('{}.png'.format(filename), bbox_inches='tight')
172 plt.close()