plotastro 1.0.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
plotastro/_core.py ADDED
@@ -0,0 +1,256 @@
1
+ """Journal definitions, style activation and figure sizing."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from pathlib import Path
6
+
7
+ import matplotlib as mpl
8
+ import matplotlib.pyplot as plt
9
+
10
+ STYLE_DIR = Path(__file__).resolve().parent / "styles"
11
+
12
+ #: Golden ratio (height/width) used for default figure heights.
13
+ GOLDEN = (5 ** 0.5 - 1) / 2 # 0.618...
14
+
15
+ _SERIF_TEX = r"\usepackage{newtxtext}\usepackage{newtxmath}"
16
+ _SANS_TEX = (r"\usepackage{helvet}\usepackage{sansmath}\sansmath"
17
+ r"\renewcommand{\familydefault}{\sfdefault}")
18
+
19
+ #: Text-block widths in LaTeX points (1 pt = 1/72.27 inch) per journal,
20
+ #: the style sheet each journal uses, and its LaTeX font preamble.
21
+ JOURNALS = {
22
+ "mnras": {"column": 240.0, "full": 504.0, "style": "mnras",
23
+ "tex": _SERIF_TEX,
24
+ "name": "Monthly Notices of the RAS"},
25
+ "rasti": {"column": 240.0, "full": 504.0, "style": "rasti",
26
+ "tex": _SERIF_TEX,
27
+ "name": "RAS Techniques and Instruments"},
28
+ "aanda": {"column": 250.38, "full": 512.15, "style": "aanda",
29
+ "tex": _SERIF_TEX,
30
+ "name": "Astronomy & Astrophysics"},
31
+ "apj": {"column": 242.26653, "full": 513.11743, "style": "apj",
32
+ "tex": _SERIF_TEX,
33
+ "name": "The Astrophysical Journal (AASTeX)"},
34
+ "oja": {"column": 245.26653, "full": 508.0, "style": "oja",
35
+ "tex": _SERIF_TEX,
36
+ "name": "The Open Journal of Astrophysics"},
37
+ "prd": {"column": 246.0, "full": 510.0, "style": "prd",
38
+ "tex": _SERIF_TEX,
39
+ "name": "Physical Review D (REVTeX 4.2)"},
40
+ "jcap": {"column": 455.24, "full": 455.24, "style": "jcap",
41
+ "tex": _SERIF_TEX,
42
+ "name": "J. of Cosmology and Astroparticle Physics"},
43
+ "natastro": {"column": 253.23, "full": 520.68, "style": "natastro",
44
+ "tex": _SANS_TEX,
45
+ "name": "Nature Astronomy"},
46
+ # Not journals, but handy width presets (they use the MNRAS look):
47
+ "thesis": {"column": 426.79135, "full": 426.79135, "style": "mnras",
48
+ "tex": _SERIF_TEX,
49
+ "name": "A4 thesis text width"},
50
+ "beamer": {"column": 307.28987, "full": 307.28987, "style": "mnras",
51
+ "tex": _SERIF_TEX,
52
+ "name": "Beamer slide text width"},
53
+ }
54
+
55
+ _ALIASES = {
56
+ "a&a": "aanda", "aa": "aanda", "astronomy&astrophysics": "aanda",
57
+ "apjl": "apj", "aj": "apj", "aas": "apj", "aastex": "apj",
58
+ "openjournal": "oja", "theoj": "oja", "openjournalofastrophysics": "oja",
59
+ "prl": "prd", "aps": "prd", "revtex": "prd",
60
+ "nature": "natastro", "natureastronomy": "natastro", "natastron": "natastro",
61
+ "mnras_full": "mnras", # legacy name from the old set_size() API
62
+ }
63
+
64
+ _state = {"journal": "mnras"}
65
+
66
+
67
+ def _resolve(journal):
68
+ key = str(journal).lower().replace(" ", "").replace("-", "")
69
+ key = _ALIASES.get(key, key)
70
+ if key not in JOURNALS:
71
+ options = ", ".join(sorted(JOURNALS))
72
+ raise ValueError(f"Unknown journal {journal!r}. Choose one of: {options}")
73
+ return key
74
+
75
+
76
+ def current_journal():
77
+ """Name of the journal activated by the last :func:`set_style` call."""
78
+ return _state["journal"]
79
+
80
+
81
+ # ----------------------------------------------------------------------
82
+ # Style activation
83
+ # ----------------------------------------------------------------------
84
+
85
+ def set_style(journal="mnras", *, usetex=False, grid=None, **rc_overrides):
86
+ """Activate the plotting style for a journal.
87
+
88
+ Parameters
89
+ ----------
90
+ journal : str
91
+ One of ``"mnras"``, ``"rasti"``, ``"aanda"`` (aliases ``"a&a"``,
92
+ ``"aa"``), ``"apj"`` (aliases ``"apjl"``, ``"aastex"``), ``"oja"``,
93
+ ``"prd"`` (aliases ``"prl"``, ``"revtex"``), ``"jcap"``,
94
+ ``"natastro"`` (alias ``"nature"``), ``"thesis"`` or ``"beamer"``.
95
+ usetex : bool, optional
96
+ If True, render all text with a real LaTeX installation using
97
+ fonts matching the journal (newtx Times for the serif journals,
98
+ Helvetica for Nature Astronomy). Default False (portable mathtext).
99
+ grid : bool, optional
100
+ Override the style's grid setting (the styles default to a
101
+ subtle grid; pass ``grid=False`` for a clean journal look).
102
+ **rc_overrides
103
+ Any extra rcParams, e.g. ``set_style("mnras", **{"font.size": 10})``.
104
+
105
+ Examples
106
+ --------
107
+ >>> pa.set_style("aanda")
108
+ >>> pa.set_style("mnras", usetex=True, grid=False)
109
+ """
110
+ key = _resolve(journal)
111
+ style_file = STYLE_DIR / f"{JOURNALS[key]['style']}.mplstyle"
112
+ plt.style.use(style_file)
113
+ _state["journal"] = key
114
+ # Presets sharing a style file (thesis, beamer) still get the right
115
+ # default figure size:
116
+ mpl.rcParams["figure.figsize"] = figsize("column", journal=key)
117
+ if usetex:
118
+ mpl.rcParams.update({
119
+ "text.usetex": True,
120
+ "text.latex.preamble": JOURNALS[key]["tex"],
121
+ })
122
+ if grid is not None:
123
+ mpl.rcParams["axes.grid"] = bool(grid)
124
+ if rc_overrides:
125
+ mpl.rcParams.update(rc_overrides)
126
+
127
+
128
+ #: Alias for :func:`set_style`, for those who prefer ``pa.use("mnras")`` —
129
+ #: after which everything is plain matplotlib.
130
+ use = set_style
131
+
132
+
133
+ # ----------------------------------------------------------------------
134
+ # Figure sizing
135
+ # ----------------------------------------------------------------------
136
+
137
+ def figsize(width="column", *, journal=None, fraction=1.0, nrows=1, ncols=1,
138
+ aspect=GOLDEN, height=None):
139
+ """Figure dimensions (inches) that match the journal's text layout,
140
+ so the figure is never rescaled (and its fonts shrunk) by LaTeX.
141
+
142
+ Parameters
143
+ ----------
144
+ width : {"column", "full"} or float
145
+ ``"column"`` for a one-column figure, ``"full"`` for the full
146
+ text width, or a number = a custom width in LaTeX points
147
+ (get yours with ``\\the\\columnwidth`` in your .tex file).
148
+ journal : str, optional
149
+ Journal to size for; defaults to the one from the last
150
+ :func:`set_style` call.
151
+ fraction : float, optional
152
+ Fraction of that width to occupy (e.g. 0.5 for half a column).
153
+ nrows, ncols : int, optional
154
+ Subplot grid shape; the height scales so each panel keeps the
155
+ requested aspect ratio.
156
+ aspect : float, optional
157
+ Height/width ratio of one panel. Default: golden ratio (0.618).
158
+ Use ``aspect=1`` for square panels.
159
+ height : float, optional
160
+ Explicit figure height in inches (overrides ``aspect``).
161
+
162
+ Returns
163
+ -------
164
+ (width_in, height_in) : tuple of float
165
+ """
166
+ key = _resolve(journal) if journal is not None else _state["journal"]
167
+ if isinstance(width, str):
168
+ w = width.lower()
169
+ if w in ("column", "col", "onecolumn", "one", "single"):
170
+ width_pt = JOURNALS[key]["column"]
171
+ elif w in ("full", "fullwidth", "two", "twocolumn", "page", "text"):
172
+ width_pt = JOURNALS[key]["full"]
173
+ else:
174
+ raise ValueError(
175
+ f"width must be 'column', 'full' or a number of points, got {width!r}")
176
+ else:
177
+ width_pt = float(width)
178
+
179
+ fig_width_in = width_pt * fraction / 72.27
180
+ if height is not None:
181
+ fig_height_in = float(height)
182
+ else:
183
+ fig_height_in = fig_width_in * aspect * (nrows / ncols)
184
+ return (fig_width_in, fig_height_in)
185
+
186
+
187
+ def subplots(nrows=1, ncols=1, *, width="column", journal=None, fraction=1.0,
188
+ aspect=GOLDEN, height=None, **kwargs):
189
+ """`plt.subplots` with the figure size computed by :func:`figsize`.
190
+
191
+ Examples
192
+ --------
193
+ >>> fig, ax = pa.subplots() # one-column figure
194
+ >>> fig, axes = pa.subplots(2, 2, width="full") # full-width 2x2 grid
195
+ >>> fig, ax = pa.subplots(aspect=1) # square panel
196
+ """
197
+ if "figsize" not in kwargs:
198
+ kwargs["figsize"] = figsize(width, journal=journal, fraction=fraction,
199
+ nrows=nrows, ncols=ncols, aspect=aspect,
200
+ height=height)
201
+ return plt.subplots(nrows, ncols, **kwargs)
202
+
203
+
204
+ def savefig(name, fig=None, formats=("pdf",), **kwargs):
205
+ """Save a figure under one or more formats at once.
206
+
207
+ Parameters
208
+ ----------
209
+ name : str or Path
210
+ Output path without extension (a known extension is stripped).
211
+ fig : Figure, optional
212
+ Defaults to the current figure.
213
+ formats : sequence of str, optional
214
+ e.g. ``("pdf", "png")`` to get both a vector file for the paper
215
+ and a raster preview.
216
+ **kwargs
217
+ Forwarded to ``fig.savefig`` (e.g. ``dpi=600``).
218
+
219
+ Returns
220
+ -------
221
+ list of str : the files written.
222
+ """
223
+ fig = fig if fig is not None else plt.gcf()
224
+ base = Path(name)
225
+ if base.suffix.lower() in (".pdf", ".png", ".eps", ".svg", ".jpg", ".tiff"):
226
+ formats = (base.suffix[1:],)
227
+ base = base.with_suffix("")
228
+ written = []
229
+ for ext in formats:
230
+ out = f"{base}.{ext}"
231
+ fig.savefig(out, **kwargs)
232
+ written.append(out)
233
+ return written
234
+
235
+
236
+ # ----------------------------------------------------------------------
237
+ # Backwards compatibility with the original myfigsize.set_size()
238
+ # ----------------------------------------------------------------------
239
+
240
+ def set_size(width="mnras", fraction=1, subplots=(1, 1), hight_ratio=1):
241
+ """Deprecated — use :func:`figsize` instead. Kept so old scripts run.
242
+
243
+ ``set_size('mnras')`` == ``figsize('column', journal='mnras')`` and
244
+ ``set_size('mnras_full')`` == ``figsize('full', journal='mnras')``.
245
+ """
246
+ if width == "mnras_full":
247
+ return figsize("full", journal="mnras", fraction=fraction,
248
+ nrows=subplots[0], ncols=subplots[1],
249
+ aspect=GOLDEN * hight_ratio)
250
+ if isinstance(width, str):
251
+ return figsize("column", journal=width, fraction=fraction,
252
+ nrows=subplots[0], ncols=subplots[1],
253
+ aspect=GOLDEN * hight_ratio)
254
+ return figsize(width, fraction=fraction,
255
+ nrows=subplots[0], ncols=subplots[1],
256
+ aspect=GOLDEN * hight_ratio)
plotastro/_extras.py ADDED
@@ -0,0 +1,187 @@
1
+ """Markers, line styles, property cyclers, panel labels, reference charts."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import functools
6
+ import operator
7
+ import string
8
+
9
+ import matplotlib.pyplot as plt
10
+ from cycler import cycler
11
+
12
+ from ._colors import COLORS, CYCLE
13
+ from ._core import figsize
14
+
15
+ #: A marker sequence that stays distinguishable at small sizes.
16
+ MARKERS = ["o", "s", "^", "D", "v", "p", "*", "X"]
17
+
18
+ #: Named dash patterns. The tuples are matplotlib (offset, (on, off, ...))
19
+ #: dash specs — they scale with the line width and print cleanly.
20
+ LINESTYLES = {
21
+ "solid": "-",
22
+ "dashed": (0, (5, 2)),
23
+ "dotted": (0, (1, 1.5)),
24
+ "dashdot": (0, (5, 2, 1, 2)),
25
+ "long dash": (0, (9, 3)),
26
+ "dash dot dot": (0, (5, 2, 1, 2, 1, 2)),
27
+ "densely dotted": (0, (1, 0.8)),
28
+ "loosely dashed": (0, (5, 6)),
29
+ }
30
+
31
+
32
+ def style_cycler(n=None, *, colors=True, markers=False, linestyles=False):
33
+ """Build a property cycler that pairs colours with markers and/or
34
+ dash patterns, so lines stay distinguishable in greyscale and for
35
+ colour-blind readers (redundant encoding).
36
+
37
+ Parameters
38
+ ----------
39
+ n : int, optional
40
+ Number of entries (default: length of the colour cycle, or 8
41
+ when markers/linestyles are included).
42
+ colors, markers, linestyles : bool
43
+ Which properties to cycle together.
44
+
45
+ Examples
46
+ --------
47
+ >>> ax.set_prop_cycle(pa.style_cycler(markers=True))
48
+ >>> ax.set_prop_cycle(pa.style_cycler(linestyles=True))
49
+ >>> plt.rc("axes", prop_cycle=pa.style_cycler(markers=True)) # globally
50
+ """
51
+ if n is None:
52
+ n = len(CYCLE) if not (markers or linestyles) else min(len(CYCLE), 8)
53
+ parts = []
54
+ if colors:
55
+ parts.append(cycler(color=(CYCLE * 3)[:n]))
56
+ if markers:
57
+ parts.append(cycler(marker=(MARKERS * 3)[:n]))
58
+ if linestyles:
59
+ parts.append(cycler(linestyle=(list(LINESTYLES.values()) * 3)[:n]))
60
+ if not parts:
61
+ raise ValueError("Enable at least one of colors/markers/linestyles.")
62
+ return functools.reduce(operator.add, parts)
63
+
64
+
65
+ # ----------------------------------------------------------------------
66
+ # Panel labels
67
+ # ----------------------------------------------------------------------
68
+
69
+ _PANEL_POSITIONS = {
70
+ # loc: (x, y, ha, va) in axes coordinates
71
+ "upper left": (0.05, 0.95, "left", "top"),
72
+ "upper right": (0.95, 0.95, "right", "top"),
73
+ "lower left": (0.05, 0.05, "left", "bottom"),
74
+ "lower right": (0.95, 0.05, "right", "bottom"),
75
+ "outside": (0.0, 1.02, "left", "bottom"),
76
+ }
77
+
78
+
79
+ def label_panels(axes, fmt="({})", loc="upper left", uppercase=False,
80
+ labels=None, **text_kw):
81
+ """Stamp (a), (b), (c), ... on a grid of subplots, the way most
82
+ journals want multi-panel figures labelled.
83
+
84
+ Parameters
85
+ ----------
86
+ axes : Axes, sequence of Axes, or array from plt.subplots
87
+ Labelled in the order given (arrays are flattened row-major).
88
+ fmt : str, optional
89
+ Applied to each letter; e.g. ``"({})"`` -> "(a)", ``"{}."`` -> "a.".
90
+ loc : str, optional
91
+ One of "upper left", "upper right", "lower left", "lower right",
92
+ or "outside" (above the top-left corner — the Nature convention,
93
+ usually combined with ``fmt="{}"`` and bold text).
94
+ uppercase : bool, optional
95
+ Use A, B, C instead of a, b, c.
96
+ labels : sequence of str, optional
97
+ Explicit labels, overriding the alphabet.
98
+ **text_kw
99
+ Forwarded to ``ax.text`` (e.g. ``fontweight="bold"``).
100
+
101
+ Returns
102
+ -------
103
+ list of the Text objects created.
104
+
105
+ Examples
106
+ --------
107
+ >>> fig, axes = pa.subplots(2, 2, width="full")
108
+ >>> pa.label_panels(axes)
109
+ >>> pa.label_panels(axes, loc="outside", fmt="{}", fontweight="bold")
110
+ """
111
+ if hasattr(axes, "flat"): # numpy array from plt.subplots
112
+ axes = list(axes.flat)
113
+ elif not hasattr(axes, "__iter__"):
114
+ axes = [axes]
115
+ if loc not in _PANEL_POSITIONS:
116
+ options = ", ".join(_PANEL_POSITIONS)
117
+ raise ValueError(f"loc must be one of: {options}; got {loc!r}")
118
+ x, y, ha, va = _PANEL_POSITIONS[loc]
119
+ letters = string.ascii_uppercase if uppercase else string.ascii_lowercase
120
+ if labels is None:
121
+ labels = [fmt.format(letters[i]) for i in range(len(axes))]
122
+ texts = []
123
+ for ax, label in zip(axes, labels):
124
+ texts.append(ax.text(x, y, label, transform=ax.transAxes,
125
+ ha=ha, va=va, **text_kw))
126
+ return texts
127
+
128
+
129
+ # ----------------------------------------------------------------------
130
+ # Reference charts (used in the tutorial and README)
131
+ # ----------------------------------------------------------------------
132
+
133
+ def show_colors(palette=None, title="Default colour-blind-friendly cycle"):
134
+ """Swatch chart of a palette dict (default: the style's colour cycle)."""
135
+ palette = palette if palette is not None else COLORS
136
+ names = list(palette)
137
+ fig, ax = plt.subplots(
138
+ figsize=figsize("full", journal="mnras", fraction=0.9,
139
+ height=0.32 * len(names) + 0.5))
140
+ ax.set_axis_off()
141
+ ax.set_title(title)
142
+ for i, name in enumerate(names):
143
+ y = len(names) - 1 - i
144
+ ax.add_patch(plt.Rectangle((0, y + 0.1), 1.6, 0.8,
145
+ color=palette[name], ec="0.2", lw=0.4))
146
+ ax.text(1.75, y + 0.5, f"C{i} · {name} · {str(palette[name]).upper()}",
147
+ va="center", ha="left", fontsize=8, family="monospace")
148
+ ax.set_xlim(0, 6)
149
+ ax.set_ylim(0, len(names))
150
+ return fig
151
+
152
+
153
+ def show_markers():
154
+ """Reference chart of the marker sequence (and a few more)."""
155
+ extra = ["<", ">", "h", "8", "P", "d", "x", "+"]
156
+ all_markers = MARKERS + extra
157
+ fig, ax = plt.subplots(
158
+ figsize=figsize("full", journal="mnras", fraction=0.9, height=1.6))
159
+ ax.set_axis_off()
160
+ ax.set_title("Markers — first row is plotastro.MARKERS")
161
+ for i, m in enumerate(all_markers):
162
+ row, col = divmod(i, 8)
163
+ y = 1.4 - row
164
+ ax.plot(col, y, marker=m, ms=7, color=CYCLE[col % len(CYCLE)],
165
+ ls="none", clip_on=False)
166
+ ax.text(col, y - 0.42, repr(m), ha="center", va="top", fontsize=8,
167
+ family="monospace")
168
+ ax.set_xlim(-0.5, 7.5)
169
+ ax.set_ylim(-0.7, 2.0)
170
+ return fig
171
+
172
+
173
+ def show_linestyles():
174
+ """Reference chart of the named dash patterns in LINESTYLES."""
175
+ fig, ax = plt.subplots(
176
+ figsize=figsize("full", journal="mnras", fraction=0.9,
177
+ height=0.34 * len(LINESTYLES) + 0.5))
178
+ ax.set_axis_off()
179
+ ax.set_title("Named line styles — plotastro.LINESTYLES")
180
+ for i, (name, ls) in enumerate(LINESTYLES.items()):
181
+ y = len(LINESTYLES) - 1 - i
182
+ ax.plot([0.35, 1.0], [y, y], ls=ls, lw=1.4,
183
+ color=CYCLE[i % len(CYCLE)])
184
+ ax.text(0.32, y, name, ha="right", va="center", fontsize=8)
185
+ ax.set_xlim(0, 1.02)
186
+ ax.set_ylim(-0.6, len(LINESTYLES) - 0.4)
187
+ return fig
@@ -0,0 +1,101 @@
1
+ # =====================================================================
2
+ # aanda.mplstyle — Astronomy & Astrophysics (A&A)
3
+ #
4
+ # Figure widths:
5
+ # one column : 250.38 pt = 3.46 in (88 mm)
6
+ # full width : 512.15 pt = 7.09 in (180 mm)
7
+ # (from the A&A author guide: 88 mm / 170-180 mm)
8
+ # The default figsize below is one column wide with a golden-ratio
9
+ # height. For other sizes use plotastro.figsize() / plotastro.subplots().
10
+ #
11
+ # Colours: colour-blind-friendly cycle — see the README for details.
12
+ # Generated by tools/generate_styles.py — edit that, not this file.
13
+ #
14
+ # Usage: import plotastro; plotastro.set_style("aanda")
15
+ # or: import plotastro; plt.style.use("aanda")
16
+ # =====================================================================
17
+
18
+ ## ---- Lines & markers ------------------------------------------------
19
+ lines.linewidth : 1.2
20
+ lines.markersize : 4
21
+ lines.markeredgewidth : 0.8
22
+ errorbar.capsize : 2
23
+ patch.linewidth : 0.8
24
+
25
+ ## ---- Fonts ----------------------------------------------------------
26
+ font.family : serif
27
+ font.serif : Times New Roman, Times, Nimbus Roman, STIXGeneral, DejaVu Serif
28
+ font.size : 9
29
+ mathtext.fontset : stix # Times-compatible maths without LaTeX
30
+
31
+ # Full LaTeX text rendering (needs a working LaTeX installation).
32
+ # Uncomment below, or call plotastro.set_style("aanda", usetex=True).
33
+ #text.usetex : True
34
+ #text.latex.preamble : \usepackage{newtxtext}\usepackage{newtxmath}
35
+
36
+ ## ---- Axes -----------------------------------------------------------
37
+ axes.linewidth : 0.6
38
+ axes.labelsize : medium
39
+ axes.titlesize : medium
40
+ axes.labelpad : 3
41
+ axes.axisbelow : True # grid behind the data
42
+ axes.formatter.use_mathtext: True
43
+ axes.xmargin : 0.03
44
+ axes.ymargin : 0.05
45
+
46
+ # Colour-blind-friendly colour cycle (see README, "The colour palette")
47
+ axes.prop_cycle : cycler('color', ['377eb8', 'ff7f00', '4daf4a', 'f781bf', 'a65628', '984ea3', '999999', 'e41a1c', 'dede00', 'a2c8ec', 'ffbc79', 'ababab'])
48
+
49
+ ## ---- Grid (subtle; set axes.grid: False to disable) -----------------
50
+ axes.grid : True
51
+ grid.linewidth : 0.4
52
+ grid.alpha : 0.25
53
+
54
+ ## ---- Ticks: all four sides, pointing in, with minors ----------------
55
+ xtick.direction : in
56
+ xtick.top : True
57
+ xtick.bottom : True
58
+ xtick.minor.visible : True
59
+ xtick.major.size : 3.5
60
+ xtick.minor.size : 2
61
+ xtick.major.width : 0.6
62
+ xtick.minor.width : 0.4
63
+ xtick.labelsize : small # ~1 pt below the base font size
64
+
65
+ ytick.direction : in
66
+ ytick.left : True
67
+ ytick.right : True
68
+ ytick.minor.visible : True
69
+ ytick.major.size : 3.5
70
+ ytick.minor.size : 2
71
+ ytick.major.width : 0.6
72
+ ytick.minor.width : 0.4
73
+ ytick.labelsize : small
74
+
75
+ ## ---- Legend ---------------------------------------------------------
76
+ legend.fontsize : small
77
+ legend.title_fontsize : small
78
+ legend.frameon : False
79
+ legend.handlelength : 1.8
80
+ legend.handletextpad : 0.5
81
+ legend.labelspacing : 0.3
82
+ legend.columnspacing : 1.2
83
+ legend.borderaxespad : 0.4
84
+
85
+ ## ---- Figure ---------------------------------------------------------
86
+ figure.figsize : 3.4646, 2.1412 # one column, golden ratio
87
+ figure.dpi : 150 # on-screen / notebook display
88
+ figure.titlesize : medium
89
+ figure.constrained_layout.use : True # no cut-off labels
90
+
91
+ ## ---- Images ---------------------------------------------------------
92
+ image.cmap : viridis
93
+ #image.origin : lower # uncomment for the astro image convention
94
+
95
+ ## ---- Saving ---------------------------------------------------------
96
+ savefig.format : pdf # journals prefer vector formats
97
+ savefig.dpi : 450 # comfortably above journal raster minimums
98
+ savefig.bbox : tight
99
+ savefig.pad_inches : 0.02
100
+ pdf.fonttype : 42 # embed TrueType fonts (no Type-3)
101
+ ps.fonttype : 42
@@ -0,0 +1,101 @@
1
+ # =====================================================================
2
+ # apj.mplstyle — The Astrophysical Journal (ApJ / ApJL, AASTeX v6.3+)
3
+ #
4
+ # Figure widths:
5
+ # one column : 242.27 pt = 3.35 in
6
+ # full width : 513.12 pt = 7.10 in
7
+ # (from the aastex631 two-column class)
8
+ # The default figsize below is one column wide with a golden-ratio
9
+ # height. For other sizes use plotastro.figsize() / plotastro.subplots().
10
+ #
11
+ # Colours: colour-blind-friendly cycle — see the README for details.
12
+ # Generated by tools/generate_styles.py — edit that, not this file.
13
+ #
14
+ # Usage: import plotastro; plotastro.set_style("apj")
15
+ # or: import plotastro; plt.style.use("apj")
16
+ # =====================================================================
17
+
18
+ ## ---- Lines & markers ------------------------------------------------
19
+ lines.linewidth : 1.2
20
+ lines.markersize : 4
21
+ lines.markeredgewidth : 0.8
22
+ errorbar.capsize : 2
23
+ patch.linewidth : 0.8
24
+
25
+ ## ---- Fonts ----------------------------------------------------------
26
+ font.family : serif
27
+ font.serif : Times New Roman, Times, Nimbus Roman, STIXGeneral, DejaVu Serif
28
+ font.size : 9
29
+ mathtext.fontset : stix # Times-compatible maths without LaTeX
30
+
31
+ # Full LaTeX text rendering (needs a working LaTeX installation).
32
+ # Uncomment below, or call plotastro.set_style("apj", usetex=True).
33
+ #text.usetex : True
34
+ #text.latex.preamble : \usepackage{newtxtext}\usepackage{newtxmath}
35
+
36
+ ## ---- Axes -----------------------------------------------------------
37
+ axes.linewidth : 0.6
38
+ axes.labelsize : medium
39
+ axes.titlesize : medium
40
+ axes.labelpad : 3
41
+ axes.axisbelow : True # grid behind the data
42
+ axes.formatter.use_mathtext: True
43
+ axes.xmargin : 0.03
44
+ axes.ymargin : 0.05
45
+
46
+ # Colour-blind-friendly colour cycle (see README, "The colour palette")
47
+ axes.prop_cycle : cycler('color', ['377eb8', 'ff7f00', '4daf4a', 'f781bf', 'a65628', '984ea3', '999999', 'e41a1c', 'dede00', 'a2c8ec', 'ffbc79', 'ababab'])
48
+
49
+ ## ---- Grid (subtle; set axes.grid: False to disable) -----------------
50
+ axes.grid : True
51
+ grid.linewidth : 0.4
52
+ grid.alpha : 0.25
53
+
54
+ ## ---- Ticks: all four sides, pointing in, with minors ----------------
55
+ xtick.direction : in
56
+ xtick.top : True
57
+ xtick.bottom : True
58
+ xtick.minor.visible : True
59
+ xtick.major.size : 3.5
60
+ xtick.minor.size : 2
61
+ xtick.major.width : 0.6
62
+ xtick.minor.width : 0.4
63
+ xtick.labelsize : small # ~1 pt below the base font size
64
+
65
+ ytick.direction : in
66
+ ytick.left : True
67
+ ytick.right : True
68
+ ytick.minor.visible : True
69
+ ytick.major.size : 3.5
70
+ ytick.minor.size : 2
71
+ ytick.major.width : 0.6
72
+ ytick.minor.width : 0.4
73
+ ytick.labelsize : small
74
+
75
+ ## ---- Legend ---------------------------------------------------------
76
+ legend.fontsize : small
77
+ legend.title_fontsize : small
78
+ legend.frameon : False
79
+ legend.handlelength : 1.8
80
+ legend.handletextpad : 0.5
81
+ legend.labelspacing : 0.3
82
+ legend.columnspacing : 1.2
83
+ legend.borderaxespad : 0.4
84
+
85
+ ## ---- Figure ---------------------------------------------------------
86
+ figure.figsize : 3.3522, 2.0718 # one column, golden ratio
87
+ figure.dpi : 150 # on-screen / notebook display
88
+ figure.titlesize : medium
89
+ figure.constrained_layout.use : True # no cut-off labels
90
+
91
+ ## ---- Images ---------------------------------------------------------
92
+ image.cmap : viridis
93
+ #image.origin : lower # uncomment for the astro image convention
94
+
95
+ ## ---- Saving ---------------------------------------------------------
96
+ savefig.format : pdf # journals prefer vector formats
97
+ savefig.dpi : 450 # comfortably above journal raster minimums
98
+ savefig.bbox : tight
99
+ savefig.pad_inches : 0.02
100
+ pdf.fonttype : 42 # embed TrueType fonts (no Type-3)
101
+ ps.fonttype : 42