myplotlib 1.6.0__tar.gz → 1.7.0__tar.gz

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.
Files changed (69) hide show
  1. {myplotlib-1.6.0 → myplotlib-1.7.0}/.gitignore +4 -1
  2. {myplotlib-1.6.0 → myplotlib-1.7.0}/PKG-INFO +3 -1
  3. {myplotlib-1.6.0 → myplotlib-1.7.0}/myplotlib/__init__.py +12 -9
  4. {myplotlib-1.6.0 → myplotlib-1.7.0}/myplotlib/plots.py +307 -149
  5. {myplotlib-1.6.0 → myplotlib-1.7.0}/myplotlib/tests.py +2 -1
  6. {myplotlib-1.6.0 → myplotlib-1.7.0}/pyproject.toml +6 -8
  7. myplotlib-1.6.0/.github/workflows/pypi-publish.yml +0 -15
  8. myplotlib-1.6.0/.taplo.toml +0 -6
  9. myplotlib-1.6.0/.vscode/extensions.json +0 -8
  10. myplotlib-1.6.0/.vscode/settings.json +0 -7
  11. myplotlib-1.6.0/MANIFEST.in +0 -6
  12. myplotlib-1.6.0/previews/classic_dark.png +0 -0
  13. myplotlib-1.6.0/previews/classic_light.png +0 -0
  14. myplotlib-1.6.0/previews/export_previews.py +0 -30
  15. myplotlib-1.6.0/previews/fancy_dark.png +0 -0
  16. myplotlib-1.6.0/previews/fancy_light.png +0 -0
  17. myplotlib-1.6.0/previews/latex.png +0 -0
  18. myplotlib-1.6.0/previews/mono_dark.png +0 -0
  19. myplotlib-1.6.0/previews/mono_light.png +0 -0
  20. myplotlib-1.6.0/previews/plain.png +0 -0
  21. myplotlib-1.6.0/shell.nix +0 -45
  22. {myplotlib-1.6.0 → myplotlib-1.7.0}/LICENSE +0 -0
  23. {myplotlib-1.6.0 → myplotlib-1.7.0}/README.md +0 -0
  24. {myplotlib-1.6.0 → myplotlib-1.7.0}/myplotlib/assets/classic.dark.mplstyle +0 -0
  25. {myplotlib-1.6.0 → myplotlib-1.7.0}/myplotlib/assets/classic.light.mplstyle +0 -0
  26. {myplotlib-1.6.0 → myplotlib-1.7.0}/myplotlib/assets/colormaps/bipolar.csv +0 -0
  27. {myplotlib-1.6.0 → myplotlib-1.7.0}/myplotlib/assets/colormaps/colt.csv +0 -0
  28. {myplotlib-1.6.0 → myplotlib-1.7.0}/myplotlib/assets/colormaps/fire.csv +0 -0
  29. {myplotlib-1.6.0 → myplotlib-1.7.0}/myplotlib/assets/colormaps/idl.csv +0 -0
  30. {myplotlib-1.6.0 → myplotlib-1.7.0}/myplotlib/assets/colormaps/sunrise.csv +0 -0
  31. {myplotlib-1.6.0 → myplotlib-1.7.0}/myplotlib/assets/colormaps/thermal.csv +0 -0
  32. {myplotlib-1.6.0 → myplotlib-1.7.0}/myplotlib/assets/colormaps/vanilla.csv +0 -0
  33. {myplotlib-1.6.0 → myplotlib-1.7.0}/myplotlib/assets/fancy.dark.mplstyle +0 -0
  34. {myplotlib-1.6.0 → myplotlib-1.7.0}/myplotlib/assets/fancy.light.mplstyle +0 -0
  35. {myplotlib-1.6.0 → myplotlib-1.7.0}/myplotlib/assets/fonts/AppleChancery.ttf +0 -0
  36. {myplotlib-1.6.0 → myplotlib-1.7.0}/myplotlib/assets/fonts/EBGaramond/EBGaramond-Bold.ttf +0 -0
  37. {myplotlib-1.6.0 → myplotlib-1.7.0}/myplotlib/assets/fonts/EBGaramond/EBGaramond-BoldItalic.ttf +0 -0
  38. {myplotlib-1.6.0 → myplotlib-1.7.0}/myplotlib/assets/fonts/EBGaramond/EBGaramond-ExtraBold.ttf +0 -0
  39. {myplotlib-1.6.0 → myplotlib-1.7.0}/myplotlib/assets/fonts/EBGaramond/EBGaramond-ExtraBoldItalic.ttf +0 -0
  40. {myplotlib-1.6.0 → myplotlib-1.7.0}/myplotlib/assets/fonts/EBGaramond/EBGaramond-Italic.ttf +0 -0
  41. {myplotlib-1.6.0 → myplotlib-1.7.0}/myplotlib/assets/fonts/EBGaramond/EBGaramond-Medium.ttf +0 -0
  42. {myplotlib-1.6.0 → myplotlib-1.7.0}/myplotlib/assets/fonts/EBGaramond/EBGaramond-MediumItalic.ttf +0 -0
  43. {myplotlib-1.6.0 → myplotlib-1.7.0}/myplotlib/assets/fonts/EBGaramond/EBGaramond-Regular.ttf +0 -0
  44. {myplotlib-1.6.0 → myplotlib-1.7.0}/myplotlib/assets/fonts/EBGaramond/EBGaramond-SemiBold.ttf +0 -0
  45. {myplotlib-1.6.0 → myplotlib-1.7.0}/myplotlib/assets/fonts/EBGaramond/EBGaramond-SemiBoldItalic.ttf +0 -0
  46. {myplotlib-1.6.0 → myplotlib-1.7.0}/myplotlib/assets/fonts/Hershey/AVHersheyComplexHeavy.ttf +0 -0
  47. {myplotlib-1.6.0 → myplotlib-1.7.0}/myplotlib/assets/fonts/Hershey/AVHersheyComplexHeavyItalic.ttf +0 -0
  48. {myplotlib-1.6.0 → myplotlib-1.7.0}/myplotlib/assets/fonts/Hershey/AVHersheyComplexLight.ttf +0 -0
  49. {myplotlib-1.6.0 → myplotlib-1.7.0}/myplotlib/assets/fonts/Hershey/AVHersheyComplexLightItalic.ttf +0 -0
  50. {myplotlib-1.6.0 → myplotlib-1.7.0}/myplotlib/assets/fonts/Hershey/AVHersheyComplexMedium.ttf +0 -0
  51. {myplotlib-1.6.0 → myplotlib-1.7.0}/myplotlib/assets/fonts/Hershey/AVHersheyComplexMediumItalic.ttf +0 -0
  52. {myplotlib-1.6.0 → myplotlib-1.7.0}/myplotlib/assets/fonts/Hershey/AVHersheyDuplexHeavy.ttf +0 -0
  53. {myplotlib-1.6.0 → myplotlib-1.7.0}/myplotlib/assets/fonts/Hershey/AVHersheyDuplexHeavyItalic.ttf +0 -0
  54. {myplotlib-1.6.0 → myplotlib-1.7.0}/myplotlib/assets/fonts/Hershey/AVHersheyDuplexLight.ttf +0 -0
  55. {myplotlib-1.6.0 → myplotlib-1.7.0}/myplotlib/assets/fonts/Hershey/AVHersheyDuplexLightItalic.ttf +0 -0
  56. {myplotlib-1.6.0 → myplotlib-1.7.0}/myplotlib/assets/fonts/Hershey/AVHersheyDuplexMedium.ttf +0 -0
  57. {myplotlib-1.6.0 → myplotlib-1.7.0}/myplotlib/assets/fonts/Hershey/AVHersheyDuplexMediumItalic.ttf +0 -0
  58. {myplotlib-1.6.0 → myplotlib-1.7.0}/myplotlib/assets/fonts/Hershey/AVHersheySimplexHeavy.ttf +0 -0
  59. {myplotlib-1.6.0 → myplotlib-1.7.0}/myplotlib/assets/fonts/Hershey/AVHersheySimplexHeavyItalic.ttf +0 -0
  60. {myplotlib-1.6.0 → myplotlib-1.7.0}/myplotlib/assets/fonts/Hershey/AVHersheySimplexLight.ttf +0 -0
  61. {myplotlib-1.6.0 → myplotlib-1.7.0}/myplotlib/assets/fonts/Hershey/AVHersheySimplexLightItalic.ttf +0 -0
  62. {myplotlib-1.6.0 → myplotlib-1.7.0}/myplotlib/assets/fonts/Hershey/AVHersheySimplexMedium.ttf +0 -0
  63. {myplotlib-1.6.0 → myplotlib-1.7.0}/myplotlib/assets/fonts/Hershey/AVHersheySimplexMediumItalic.ttf +0 -0
  64. {myplotlib-1.6.0 → myplotlib-1.7.0}/myplotlib/assets/latex.mplstyle +0 -0
  65. {myplotlib-1.6.0 → myplotlib-1.7.0}/myplotlib/assets/mono.dark.mplstyle +0 -0
  66. {myplotlib-1.6.0 → myplotlib-1.7.0}/myplotlib/assets/mono.light.mplstyle +0 -0
  67. {myplotlib-1.6.0 → myplotlib-1.7.0}/myplotlib/tools/__init__.py +0 -0
  68. {myplotlib-1.6.0 → myplotlib-1.7.0}/myplotlib/tools/lic.py +0 -0
  69. {myplotlib-1.6.0 → myplotlib-1.7.0}/previews/README.md +0 -0
@@ -165,4 +165,7 @@ dmypy.json
165
165
  .pytype/
166
166
 
167
167
  # Cython debug symbols
168
- cython_debug/
168
+ cython_debug/
169
+ .direnv
170
+ .envrc
171
+ .claude/
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: myplotlib
3
- Version: 1.6.0
3
+ Version: 1.7.0
4
4
  Summary: `matplotlib` binder with custom styles and routines for fast plotting
5
5
  Project-URL: Repository, https://github.com/haykh/myplotlib
6
6
  Author-email: Hayk <haykh.astro@gmail.com>
@@ -45,6 +45,8 @@ Classifier: Programming Language :: Python :: 3.9
45
45
  Classifier: Programming Language :: Python :: 3.10
46
46
  Classifier: Programming Language :: Python :: 3.11
47
47
  Classifier: Programming Language :: Python :: 3.12
48
+ Classifier: Programming Language :: Python :: 3.13
49
+ Classifier: Programming Language :: Python :: 3.14
48
50
  Classifier: Topic :: Scientific/Engineering :: Visualization
49
51
  Requires-Python: >=3.8
50
52
  Requires-Dist: matplotlib>=3.5.0
@@ -1,9 +1,11 @@
1
- __version__ = "1.6.0"
1
+ __version__ = "1.7.0"
2
2
 
3
3
 
4
4
  import os
5
+ import warnings
6
+ from pathlib import Path
5
7
  import matplotlib.pyplot as plt
6
- from matplotlib import font_manager
8
+ from matplotlib import font_manager, rc_params_from_file
7
9
 
8
10
  import myplotlib
9
11
 
@@ -57,13 +59,14 @@ def __InstallCmapFromCSV(csv):
57
59
  myplotlib_path = myplotlib.__path__[0]
58
60
  styles_path = os.path.join(myplotlib_path, "assets")
59
61
 
60
- stylesheets = {}
61
- for folder, _, _ in os.walk(styles_path):
62
- new_stylesheets = plt.style.core.read_style_directory(folder)
63
- stylesheets.update(new_stylesheets)
64
-
65
- plt.style.core.update_nested_dict(plt.style.library, stylesheets)
66
- plt.style.core.available[:] = sorted(plt.style.library.keys())
62
+ for path in Path(styles_path).rglob("*.mplstyle"):
63
+ with warnings.catch_warnings(record=True):
64
+ plt.style.library[path.stem] = rc_params_from_file(
65
+ path, use_default_template=False
66
+ )
67
+ plt.style.available[:] = sorted(
68
+ name for name in plt.style.library if not name.startswith("_")
69
+ )
67
70
 
68
71
  CMAP_DIR = os.path.join(myplotlib_path, "assets/colormaps")
69
72
  CMAPS = os.listdir(CMAP_DIR)
@@ -12,27 +12,56 @@ a collection of handy plotting functions bound around `matplotlib` with lots of
12
12
  docstrings are available for all of the functions. type, e.g., `dataPlot?` to read about the arguments passed.
13
13
  """
14
14
 
15
+ from typing import TypeAlias, Any, TypedDict, Callable
15
16
  import numpy as np
17
+ import matplotlib.colors as mcolors
18
+ from matplotlib.axes._axes import Axes as pltAxes
16
19
 
20
+ LimTypeWithNone: TypeAlias = tuple[float | None, float | None] | None
21
+ LimType: TypeAlias = tuple[float, float]
17
22
 
18
- def __stretch(left, right, pad):
23
+
24
+ def __stretch(
25
+ left: float,
26
+ right: float,
27
+ pad: float,
28
+ ) -> LimType:
29
+ """stretch the limits by a padding factor"""
19
30
  c = 0.5 * (left + right)
20
31
  d = 0.5 * (right - left)
21
32
  return (c - d * pad, c + d * pad)
22
33
 
23
34
 
24
- def __setMinMax(lims, data):
25
- if not lims:
26
- lims = (np.nanmin(data), np.nanmax(data))
27
- if lims[0] == None:
28
- lims = (np.nanmin(data), lims[1])
29
- if lims[1] == None:
30
- lims = (lims[0], np.nanmax(data))
31
- return lims
32
-
33
-
34
- def __setAxLims(ax, coords, log, pad, lim, spines):
35
- lim = __setMinMax(lim, coords)
35
+ def __setMinMax(
36
+ lims: LimTypeWithNone,
37
+ data: np.ndarray,
38
+ ) -> LimType:
39
+ """set the limits of the axis according to the data and the passed limits"""
40
+ if lims is None:
41
+ return (np.nanmin(data), np.nanmax(data))
42
+ assert (
43
+ isinstance(lims, tuple) and len(lims) == 2
44
+ ), "lims must be a tuple of length 2"
45
+ if lims[0] is None and lims[1] is None:
46
+ return (np.nanmin(data), np.nanmax(data))
47
+ if lims[0] is None and lims[1] is not None:
48
+ return (np.nanmin(data), lims[1])
49
+ if lims[1] is None and lims[0] is not None:
50
+ return (lims[0], np.nanmax(data))
51
+ assert lims[0] is not None and lims[1] is not None, "lims must not be None"
52
+ return (lims[0], lims[1])
53
+
54
+
55
+ def __setAxLims(
56
+ ax: pltAxes,
57
+ coords,
58
+ log: bool,
59
+ pad: float,
60
+ lims: LimTypeWithNone,
61
+ spines: str,
62
+ ):
63
+ """set the limits of the axis according to the data and the passed limits"""
64
+ lim = __setMinMax(lims, coords)
36
65
  # TODO: fix negative when log specified
37
66
  if pad > 0:
38
67
  ax.spines[spines].set_bounds(*lim)
@@ -43,7 +72,7 @@ def __setAxLims(ax, coords, log, pad, lim, spines):
43
72
  func_setscale = ax.set_yscale
44
73
  func_setlim = ax.set_ylim
45
74
  else:
46
- raise ValueError
75
+ raise ValueError(f"invalid `spines` value: {spines}")
47
76
  if log:
48
77
  func_setscale("log")
49
78
  p1, p2 = lim
@@ -57,7 +86,12 @@ def __setAxLims(ax, coords, log, pad, lim, spines):
57
86
  func_setlim(*__stretch(p1, p2, 1.0 + pad))
58
87
 
59
88
 
60
- def __checkDimensions2d(x, y, zz):
89
+ def __checkDimensions2d(
90
+ x: np.ndarray,
91
+ y: np.ndarray,
92
+ zz: np.ndarray,
93
+ ) -> tuple[np.ndarray, np.ndarray, np.ndarray]:
94
+ """check the dimensions of the passed 2d arrays and return them as 1d arrays"""
61
95
  x, y, zz = (
62
96
  np.array(np.squeeze(x)),
63
97
  np.array(np.squeeze(y)),
@@ -83,7 +117,11 @@ def __checkDimensions2d(x, y, zz):
83
117
  return (x, y, zz)
84
118
 
85
119
 
86
- def __findExtent(x, y, centering):
120
+ def __findExtent(
121
+ x: np.ndarray,
122
+ y: np.ndarray,
123
+ centering: str,
124
+ ) -> tuple[float, float, float, float]:
87
125
  if centering == "edge":
88
126
  dx = x[1] - x[0]
89
127
  dy = y[1] - y[0]
@@ -103,30 +141,42 @@ def __findExtent(x, y, centering):
103
141
 
104
142
 
105
143
  def dataPlot(
106
- function,
107
- ax,
108
- x,
109
- y,
110
- xlog=False,
111
- ylog=False,
112
- xlim=None,
113
- ylim=None,
114
- padx=0.0,
115
- pady=0.0,
144
+ function: Callable,
145
+ ax: pltAxes,
146
+ x: np.ndarray,
147
+ y: np.ndarray,
148
+ xlog: bool = False,
149
+ ylog: bool = False,
150
+ xlim: LimTypeWithNone = None,
151
+ ylim: LimTypeWithNone = None,
152
+ padx: float = 0.0,
153
+ pady: float = 0.0,
116
154
  **kwargs,
117
155
  ):
118
- """
119
- add a plot according to a passed function
120
-
121
- args
122
- ----------
123
- function .................... : `ax.<METHOD>` used to make the plot (e.g. `ax.step`, `ax.errorbar`)
124
- ax .......................... : matplotlib axis object
125
- x, y ........................ : 1d data arrays
126
- xlog [False], ylog [False] .. : use log in x or y direction
127
- xlim [None], ylim [None] .... : tuples of x and y limits (None = determine from data)
128
- padx [0], pady [0] .......... : add whitespace to axes in each direction (0 = no additional space)
129
- **kwargs .................... : standard matplotlib kwargs passed to `ax.<function>`
156
+ """Add a plot according to a passed function
157
+
158
+ Args
159
+ ----
160
+ function : Callable
161
+ The function to call on the axis (e.g., `ax.plot`, `ax.scatter`).
162
+ ax : pltAxes
163
+ The matplotlib axis object.
164
+ x, y : np.ndarray
165
+ The data to plot.
166
+ xlog : bool, optional
167
+ Use logarithmic scale for x-axis (default is False).
168
+ ylog : bool, optional
169
+ Use logarithmic scale for y-axis (default is False).
170
+ xlim : tuple[float | None, float | None] | None, optional
171
+ Tuple of x limits (None = determine from data) (default is None).
172
+ ylim : tuple[float | None, float | None] | None, optional
173
+ Tuple of y limits (None = determine from data) (default is None).
174
+ padx : float, optional
175
+ Add whitespace to axes in each direction (0 = no additional space) (default is 0.0).
176
+ pady : float, optional
177
+ Add whitespace to axes in each direction (0 = no additional space) (default is 0.0).
178
+ **kwargs : dict, optional
179
+ Standard matplotlib kwargs passed to `function`.
130
180
  """
131
181
  if padx != 0:
132
182
  ax.spines["top"].set_visible(False)
@@ -139,85 +189,145 @@ def dataPlot(
139
189
 
140
190
 
141
191
  def scatter(
142
- ax, x, y, xlog=False, ylog=False, xlim=None, ylim=None, padx=0.0, pady=0.0, **kwargs
192
+ ax: pltAxes,
193
+ x: np.ndarray,
194
+ y: np.ndarray,
195
+ xlog: bool = False,
196
+ ylog: bool = False,
197
+ xlim: LimTypeWithNone = None,
198
+ ylim: LimTypeWithNone = None,
199
+ padx: float = 0.0,
200
+ pady: float = 0.0,
201
+ **kwargs,
143
202
  ):
144
- """
145
- add a scatter plot to a given axis (same as `dataPlot(ax.scatter, ...)`)
146
-
147
- args
148
- ----------
149
- ax .......................... : matplotlib axis object
150
- x, y ........................ : 1d data arrays
151
- xlog [False], ylog [False] .. : use log in x or y direction
152
- xlim [None], ylim [None] .... : tuples of x and y limits (None = determine from data)
153
- padx [0], pady [0] .......... : add whitespace to axes in each direction (0 = no additional space)
154
- **kwargs .................... : standard matplotlib kwargs passed to `ax.scatter`
203
+ """Add a scatter plot to a given axis
204
+
205
+ Args
206
+ ----
207
+ ax : pltAxes
208
+ The matplotlib axis object.
209
+ x, y : np.ndarray
210
+ The data to plot.
211
+ xlog : bool, optional
212
+ Use logarithmic scale for x-axis (default is False).
213
+ ylog : bool, optional
214
+ Use logarithmic scale for y-axis (default is False).
215
+ xlim : LimTypeWithNone, optional
216
+ Tuple of x limits (None = determine from data) (default is None).
217
+ ylim : LimTypeWithNone, optional
218
+ Tuple of y limits (None = determine from data) (default is None).
219
+ padx : float, optional
220
+ Add whitespace to axes in each direction (0 = no additional space) (default is 0.0).
221
+ pady : float, optional
222
+ Add whitespace to axes in each direction (0 = no additional space) (default is 0.0).
223
+ **kwargs : dict, optional
224
+ Standard matplotlib kwargs passed to `ax.scatter`.
155
225
  """
156
226
  return dataPlot(ax.scatter, ax, x, y, xlog, ylog, xlim, ylim, padx, pady, **kwargs)
157
227
 
158
228
 
159
229
  def plot(
160
- ax, x, y, xlog=False, ylog=False, xlim=None, ylim=None, padx=0.0, pady=0.0, **kwargs
230
+ ax: pltAxes,
231
+ x: np.ndarray,
232
+ y: np.ndarray,
233
+ xlog: bool = False,
234
+ ylog: bool = False,
235
+ xlim: LimTypeWithNone = None,
236
+ ylim: LimTypeWithNone = None,
237
+ padx: float = 0.0,
238
+ pady: float = 0.0,
239
+ **kwargs,
161
240
  ):
162
- """
163
- add a simple plot to a given axis (same as `dataPlot(ax.plot, ...)`)
164
-
165
- args
166
- ----------
167
- ax .......................... : matplotlib axis object
168
- x, y ........................ : 1d data arrays
169
- xlog [False], ylog [False] .. : use log in x or y direction
170
- xlim [None], ylim [None] .... : tuples of x and y limits (None = determine from data)
171
- padx [0], pady [0] .......... : add whitespace to axes in each direction (0 = no additional space)
172
- **kwargs .................... : standard matplotlib kwargs passed to `ax.plot`
241
+ """Add a plot to a given axis (same as `dataPlot(ax.plot, ...)`)
242
+
243
+ Args
244
+ ----
245
+ ax : pltAxes
246
+ The matplotlib axis object.
247
+ x, y : np.ndarray
248
+ The data to plot.
249
+ xlog : bool, optional
250
+ Use logarithmic scale for x-axis (default is False).
251
+ ylog : bool, optional
252
+ Use logarithmic scale for y-axis (default is False).
253
+ xlim : LimTypeWithNone, optional
254
+ Tuple of x limits (None = determine from data) (default is None).
255
+ ylim : LimTypeWithNone, optional
256
+ Tuple of y limits (None = determine from data) (default is None).
257
+ padx : float, optional
258
+ Add whitespace to axes in each direction (0 = no additional space) (default is 0.0).
259
+ pady : float, optional
260
+ Add whitespace to axes in each direction (0 = no additional space) (default is 0.0).
261
+ **kwargs : dict, optional
262
+ Standard matplotlib kwargs passed to `function`.
173
263
  """
174
264
  dataPlot(ax.plot, ax, x, y, xlog, ylog, xlim, ylim, padx, pady, **kwargs)
175
265
 
176
266
 
177
267
  def plot2d(
178
- ax,
179
- x,
180
- y,
181
- zz,
182
- force_aspect=True,
183
- centering="edge",
184
- xlim=None,
185
- ylim=None,
186
- zlog=False,
187
- zlim=None,
188
- padx=0.0,
189
- pady=0.0,
190
- cbar="5%",
191
- cbar_pad=0.05,
192
- cbar_pos="right",
268
+ ax: pltAxes,
269
+ x: np.ndarray,
270
+ y: np.ndarray,
271
+ zz: np.ndarray,
272
+ force_aspect: bool = True,
273
+ centering: str = "edge",
274
+ xlim: LimTypeWithNone = None,
275
+ ylim: LimTypeWithNone = None,
276
+ zlog: bool = False,
277
+ zlim: LimTypeWithNone = None,
278
+ padx: float = 0.0,
279
+ pady: float = 0.0,
280
+ cbar: str | None = "5%",
281
+ cbar_pad: float = 0.05,
282
+ cbar_pos: str = "right",
193
283
  **kwargs,
194
284
  ):
195
- """
196
- add a 2d plot to a given axis
197
-
198
- args
199
- ----------
200
- ax .......................... : matplotlib axis object
201
- x, y ........................ : 1d or 2d arrays of coordinates
202
- force_aspect [True] ......... : force equal aspect ratio according to axes
203
- centering ['edge'] .......... : centering of x & y nodes for the data ('edge', 'center')
204
- xlim [None], ylim [None] .... : tuples of x and y limits (None = determine from x & y)
205
- zlog [False] ................ : use log in z ('True', 'False')
206
- zlim [None] ................. : tuple of z limits (None = determine from z)
207
- padx [0], pady [0] .......... : add whitespace to axes in each direction (0 = no additional space)
208
- cbar ['5%'] ................. : size of the colorbar in percent of x-axis (None = no colorbar)
209
- cbar_pad [0.05] ............. : padding of the colorbar
210
- cbar_pos ['right'] .......... : position of the colorbar ('left', 'right', 'top', 'bottom')
211
- **kwargs .................... : standard matplotlib kwargs passed to `ax.imshow`
285
+ """Add a 2d plot to a given axis
286
+
287
+ Args
288
+ ----
289
+ ax : matplotlib axis object
290
+ The axis to plot on.
291
+ x, y : 1d or 2d arrays of coordinates
292
+ The coordinates of the data to plot.
293
+ force_aspect : bool, optional
294
+ Force equal aspect ratio according to axes (default is True).
295
+ centering : str, optional
296
+ Centering of x & y nodes for the data ('edge', 'center') (default is 'edge').
297
+ xlim : tuple of float, optional
298
+ Tuple of x limits (None = determine from x) (default is None).
299
+ ylim : tuple of float, optional
300
+ Tuple of y limits (None = determine from y) (default is None).
301
+ zlog : bool, optional
302
+ Use log in z ('True', 'False') (default is False).
303
+ zlim : tuple of float, optional
304
+ Tuple of z limits (None = determine from z) (default is None).
305
+ padx : float, optional
306
+ Add whitespace to axes in each direction (0 = no additional space) (default is 0.0).
307
+ pady : float, optional
308
+ Add whitespace to axes in each direction (0 = no additional space) (default is 0.0).
309
+ cbar : str or None, optional
310
+ Size of the colorbar in percent of x-axis (None = no colorbar) (default is '5%').
311
+ cbar_pad : float, optional
312
+ Padding of the colorbar (default is 0.05).
313
+ cbar_pos : str, optional
314
+ Position of the colorbar ('left', 'right', 'top', 'bottom') (default is 'right').
315
+ **kwargs : dict, optional
316
+ Standard matplotlib kwargs passed to `ax.imshow`.
317
+
318
+ Returns
319
+ -------
320
+ None or colorbar handle
321
+ Returns `None` if `cbar` is `None`, otherwise returns the colorbar handle.
322
+
323
+ Raises
324
+ ------
325
+ AssertionError
326
+ If `centering` is not 'edge' or 'center', or if `cbar_pos` is not one of 'left', 'right', 'top', or 'bottom'.
212
327
 
213
- returns
214
- ----------
215
- `None` ...................... : if `cbar` is `None`
216
- colorbar handle ............. : if `cbar` is not `None`
217
328
  """
218
329
  from mpl_toolkits.axes_grid1 import make_axes_locatable
219
330
  import matplotlib.pyplot as plt
220
- import matplotlib as mpl
221
331
 
222
332
  assert centering in ["edge", "center"], "invalid `centering`"
223
333
  assert cbar_pos in ["left", "right", "top", "bottom"], "invalid `cbar_pos`"
@@ -227,17 +337,23 @@ def plot2d(
227
337
  extent = __findExtent(x, y, centering)
228
338
  aspect = "auto" if not force_aspect else None
229
339
  if not ("norm" in kwargs):
230
- if zlim is None:
231
- vmax = np.quantile(zz[~np.isnan(zz) & ~np.isinf(zz)], 0.95)
232
- vmin = np.quantile(zz[~np.isnan(zz) & ~np.isinf(zz)], 0.05)
340
+ zminQ = np.quantile(zz[~np.isnan(zz) & ~np.isinf(zz)], 0.05)
341
+ zmaxQ = np.quantile(zz[~np.isnan(zz) & ~np.isinf(zz)], 0.95)
342
+ if zlim is not None:
343
+ if zlim[0] is None:
344
+ vmin = zminQ
345
+ else:
346
+ vmin = zlim[0]
347
+ if zlim[1] is None:
348
+ vmax = zmaxQ
349
+ else:
350
+ vmax = zlim[1]
233
351
  else:
234
- vmin, vmax = zlim
352
+ vmin, vmax = zminQ, zmaxQ
235
353
  if zlog:
236
- if vmin < 0:
237
- vmin = vmax / 1e6
238
- norm = mpl.colors.LogNorm(vmin=vmin, vmax=vmax)
354
+ norm = mcolors.LogNorm(vmin=float(vmin), vmax=float(vmax))
239
355
  else:
240
- norm = mpl.colors.Normalize(vmin=vmin, vmax=vmax)
356
+ norm = mcolors.Normalize(vmin=float(vmin), vmax=float(vmax))
241
357
  else:
242
358
  norm = kwargs.get("norm")
243
359
  kwargs.pop("norm")
@@ -269,30 +385,53 @@ def plot2d(
269
385
 
270
386
 
271
387
  def plotVectorField(
272
- ax,
273
- x,
274
- y,
275
- fx,
276
- fy,
277
- background=None,
278
- texture_seed=None,
279
- kernel_len=31,
280
- kernel_pow=1,
281
- lic_alphamin=0.5,
282
- lic_alphamax=0.75,
283
- lic_contrast=0.33,
284
- lic_opacity=0.75,
285
- lic_cmap="binary_r",
286
- force_aspect=True,
287
- centering="edge",
288
- xlim=None,
289
- ylim=None,
290
- padx=0.0,
291
- pady=0.0,
292
- cbar="5%",
293
- cbar_pad=0.05,
388
+ ax: pltAxes,
389
+ x: np.ndarray,
390
+ y: np.ndarray,
391
+ fx: np.ndarray,
392
+ fy: np.ndarray,
393
+ background: np.ndarray | None = None,
394
+ texture_seed: int | None = None,
395
+ kernel_len: int = 31,
396
+ kernel_pow: int = 1,
397
+ lic_alphamin: float = 0.5,
398
+ lic_alphamax: float = 0.75,
399
+ lic_contrast: float = 0.33,
400
+ lic_opacity: float = 0.75,
401
+ lic_cmap: str = "binary_r",
402
+ force_aspect: bool = True,
403
+ centering: str = "edge",
404
+ xlim: tuple[float, float] | None = None,
405
+ ylim: tuple[float, float] | None = None,
406
+ padx: float = 0.0,
407
+ pady: float = 0.0,
408
+ cbar: str | None = "5%",
409
+ cbar_pad: float = 0.05,
294
410
  **kwargs,
295
411
  ):
412
+ """Add a 2D plot with a vector-field overplotted
413
+
414
+ Args
415
+ ----
416
+ ax : pltAxes
417
+ The matplotlib axis object.
418
+ x, y : np.ndarray
419
+ 1D or 2D arrays of coordinates.
420
+ fx, fy : np.ndarray
421
+ 2D arrays of the vector field components.
422
+ background : np.ndarray | None, optional
423
+ 2D array of the image background (None = `sqrt(fx^2 + fy^2)`).
424
+
425
+ texture_seed : int | None, optional
426
+ Specify a random seed to generate textures, useful when rendering movies (None = random).
427
+ kernel_len : int, optional
428
+ Kernel resolution for the LIC algorithm (default is 31).
429
+ kernel_pow : int, optional
430
+ Kernel sharpness for the LIC algorithm (default is 1).
431
+ lic_alphamin : float, optional
432
+
433
+ """
434
+
296
435
  """
297
436
  add a 2d plot with a vector-field overplotted
298
437
 
@@ -304,7 +443,7 @@ def plotVectorField(
304
443
  background [None] ........... : 2d array of the image background (None = `sqrt(fx^2 + fy^2)`)
305
444
 
306
445
  line integral convolution (lic) parameters
307
- ----------
446
+ ---------
308
447
  texture_seed [None] ......... : specify a random seed to generate textures, useful when rendering movies (None = random)
309
448
  kernel_len [31] ............. : kernel resolution for the lic algorithm
310
449
  kernel_pow [1] .............. : kernel sharpness for the lic algorithm
@@ -348,14 +487,14 @@ def plotVectorField(
348
487
  _ = np.sign(weights - np.average(weights)) * np.sqrt(
349
488
  np.abs(weights - np.average(weights))
350
489
  )
351
- alphas = matplotlib.colors.Normalize(None, None, clip=True)(_)
490
+ alphas = mcolors.Normalize(None, None, clip=True)(_)
352
491
  alphas[alphas < lic_alphamin] = 0
353
492
  alphas[alphas > lic_alphamax] = 1
354
493
  _ = (
355
494
  np.sign(weights - np.average(weights))
356
495
  * np.abs(weights - np.average(weights)) ** lic_contrast
357
496
  )
358
- colors = matplotlib.colors.Normalize(None, None)(_)
497
+ colors = mcolors.Normalize(None, None)(_)
359
498
  colors = matplotlib.colormaps[lic_cmap](colors)
360
499
  colors[..., -1] = alphas
361
500
 
@@ -392,17 +531,24 @@ def plotVectorField(
392
531
  return colorbar
393
532
 
394
533
 
534
+ class PanelDict(TypedDict):
535
+ label: str | None
536
+ field: Callable | None
537
+ cmap: str | None
538
+ norm: mcolors.Normalize | None
539
+
540
+
395
541
  def plot2dGrid(
396
- x,
397
- y,
398
- fields,
399
- panels,
400
- label_pos="title",
401
- label_args={},
402
- width=10,
403
- dpi=150,
404
- wspace=0.05,
405
- hspace=0.05,
542
+ x: np.ndarray,
543
+ y: np.ndarray,
544
+ fields: dict[str, np.ndarray],
545
+ panels: list[list[PanelDict]],
546
+ label_pos: str = "title",
547
+ label_args: dict[str, Any] = {},
548
+ width: float = 10,
549
+ dpi: int = 150,
550
+ wspace: float = 0.05,
551
+ hspace: float = 0.05,
406
552
  **kwargs,
407
553
  ):
408
554
  """
@@ -474,12 +620,14 @@ def plot2dGrid(
474
620
  for j in range(ncols):
475
621
  ax = axs[i][j]
476
622
  panel = panels[i][j]
477
-
623
+ assert "field" in panel, "panel must have a 'field' key"
624
+ field_func = panel["field"]
625
+ assert field_func is not None, "field must be a callable function"
478
626
  cbar = plot2d(
479
627
  ax,
480
628
  x,
481
629
  y,
482
- panel["field"](fields),
630
+ field_func(fields),
483
631
  norm=panel["norm"],
484
632
  cmap=panel["cmap"],
485
633
  **kwargs,
@@ -491,10 +639,20 @@ def plot2dGrid(
491
639
  ax.set(xlabel=None, xticklabels=[])
492
640
 
493
641
  if label_pos == "title":
494
- ax.set_title(panel["label"], **label_args)
642
+ assert "label" in panel, "panel must have a 'label' key"
643
+ if panel["label"] is not None:
644
+ ax.set_title(panel["label"], **label_args)
495
645
  elif label_pos == "cbar":
496
- cbar.set_label(panel["label"], **label_args)
646
+ if cbar is not None:
647
+ assert "label" in panel, "panel must have a 'label' key"
648
+ if panel["label"] is not None:
649
+ cbar.set_label(panel["label"], **label_args)
497
650
  elif label_pos == "text":
498
- ax.text(
499
- *label_coords, panel["label"], transform=ax.transAxes, **label_args
500
- )
651
+ assert "label" in panel, "panel must have a 'label' key"
652
+ if panel["label"] is not None:
653
+ ax.text(
654
+ *label_coords,
655
+ s=panel["label"],
656
+ transform=ax.transAxes,
657
+ **label_args,
658
+ )
@@ -18,6 +18,7 @@ import myplotlib.plots as myplt
18
18
  import myplotlib
19
19
 
20
20
  import matplotlib
21
+ import matplotlib.colors as mcolors
21
22
  import matplotlib.pyplot as plt
22
23
  import numpy as np
23
24
 
@@ -200,7 +201,7 @@ def testVectorPlot2d(ax=None):
200
201
  ys,
201
202
  vectors[:, :, 0],
202
203
  vectors[:, :, 1],
203
- norm=matplotlib.colors.LogNorm(1, 1e2),
204
+ norm=mcolors.LogNorm(1, 1e2),
204
205
  cmap="turbo",
205
206
  lic_contrast=1,
206
207
  )
@@ -25,6 +25,8 @@
25
25
  "Programming Language :: Python :: 3.10",
26
26
  "Programming Language :: Python :: 3.11",
27
27
  "Programming Language :: Python :: 3.12",
28
+ "Programming Language :: Python :: 3.13",
29
+ "Programming Language :: Python :: 3.14",
28
30
  ]
29
31
 
30
32
  [project.urls]
@@ -33,12 +35,8 @@
33
35
  [tool.hatch.version]
34
36
  path = "myplotlib/__init__.py"
35
37
 
36
- [tool.setuptools]
37
- include-package-data = true
38
+ [tool.hatch.build.targets.wheel]
39
+ packages = ["myplotlib"]
38
40
 
39
- [tool.setuptools.packages.find]
40
- where = [
41
- "myplotlib/assets",
42
- "myplotlib/assets/fonts",
43
- "myplotlib/assets/colormaps",
44
- ]
41
+ [tool.hatch.build.targets.sdist]
42
+ include = ["myplotlib", "README.md", "LICENSE"]
@@ -1,15 +0,0 @@
1
- name: Python package
2
-
3
- on: [push]
4
-
5
- jobs:
6
- build:
7
- runs-on: ubuntu-latest
8
-
9
- steps:
10
- - uses: actions/checkout@v3
11
- - name: Publish package
12
- if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags')
13
- uses: pypa/gh-action-pypi-publish@release/v1
14
- with:
15
- password: ${{ secrets.PYPI_API_TOKEN }}
@@ -1,6 +0,0 @@
1
- [formatting]
2
- align_entries = true
3
- indent_tables = true
4
- indent_entries = true
5
- trailing_newline = true
6
- align_comments = true
@@ -1,8 +0,0 @@
1
- {
2
- "recommendations": [
3
- "tamasfe.even-better-toml",
4
- "yy0931.mplstyle",
5
- "ms-python.black-formatter",
6
- "ms-python.python"
7
- ]
8
- }
@@ -1,7 +0,0 @@
1
- {
2
- "[toml]": {
3
- "editor.defaultFormatter": "tamasfe.even-better-toml"
4
- },
5
- "evenBetterToml.taplo.configFile.enabled": true,
6
- "evenBetterToml.taplo.configFile.path": ".taplo.toml",
7
- }
@@ -1,6 +0,0 @@
1
- include myplotlib/assets/*
2
- include myplotlib/assets/fonts/*
3
- include myplotlib/assets/colormaps/*
4
- include LICENSE
5
- include README.md
6
- include pyproject.toml
Binary file
Binary file
@@ -1,30 +0,0 @@
1
- import os
2
- import matplotlib.pyplot as plt
3
-
4
- import myplotlib
5
- import myplotlib.tests as mypltests
6
-
7
- if __name__ == "__main__":
8
- readme = ""
9
-
10
- for st, fl in [
11
- f.replace(".mplstyle", "").split(".")
12
- for f in os.listdir("myplotlib/assets")
13
- if f.endswith(".mplstyle") and f.count(".") == 2
14
- ]:
15
- with plt.style.context(f"{st}.{fl}"):
16
- mypltests.testAll()
17
- plt.savefig(f"previews/{st}_{fl}.png", dpi=300)
18
- readme += f"# `{st}.{fl}`\n\n![{st}_{fl}]({st}_{fl}.png)\n\n"
19
-
20
- with plt.style.context("latex"):
21
- mypltests.testAll()
22
- plt.savefig(f"previews/latex.png", dpi=300)
23
- readme += f"# `Latex`\n\n![Latex](latex.png)\n\n"
24
-
25
- mypltests.testAll()
26
- plt.savefig(f"previews/plain.png", dpi=300)
27
- readme += f"# `Plain`\n\n![Plain](plain.png)\n\n"
28
-
29
- with open("previews/README.md", "w") as f:
30
- f.write(readme)
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
myplotlib-1.6.0/shell.nix DELETED
@@ -1,45 +0,0 @@
1
- {
2
- pkgs ? import <nixpkgs> { },
3
- }:
4
-
5
- let
6
- name = "myplotlib";
7
- in
8
- pkgs.mkShell ({
9
- name = "${name}-env";
10
- nativeBuildInputs = with pkgs; [
11
- python312
12
- black
13
- pyright
14
- taplo
15
- vscode-langservers-extracted
16
- zlib
17
- llvmPackages_19.libcxxClang
18
- zsh
19
- ];
20
-
21
- LD_LIBRARY_PATH = pkgs.lib.makeLibraryPath [
22
- pkgs.stdenv.cc.cc
23
- pkgs.zlib
24
- ];
25
-
26
- shellHook = ''
27
- BLUE='\033[0;34m'
28
- NC='\033[0m'
29
- export SHELL=$(which zsh)
30
- export VENV_DIR="$(pwd)/.venv"
31
-
32
- if [ ! -d "$VENV_DIR" ]; then
33
- python3 -m venv "$VENV_DIR"
34
- source "$VENV_DIR/bin/activate"
35
- pip install --upgrade pip --quiet
36
- pip install -e . --quiet
37
- pip install ipykernel jupyter build --quiet
38
- else
39
- source "$VENV_DIR/bin/activate"
40
- fi
41
-
42
- echo -e "${name} nix-shell activated: ''\${BLUE}$(which python3)''\${NC}"
43
- exec $SHELL
44
- '';
45
- })
File without changes
File without changes
File without changes