py-pluto 1.1.4__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.
Files changed (73) hide show
  1. pyPLUTO/__init__.py +22 -0
  2. pyPLUTO/amr.py +745 -0
  3. pyPLUTO/baseloadmixin.py +258 -0
  4. pyPLUTO/baseloadstate.py +45 -0
  5. pyPLUTO/codes/echo_load.py +161 -0
  6. pyPLUTO/configure.py +261 -0
  7. pyPLUTO/gui/config.py +174 -0
  8. pyPLUTO/gui/custom_var.py +435 -0
  9. pyPLUTO/gui/globals.py +108 -0
  10. pyPLUTO/gui/main.py +17 -0
  11. pyPLUTO/gui/main_window.py +177 -0
  12. pyPLUTO/gui/panels.py +66 -0
  13. pyPLUTO/gui/utils.py +273 -0
  14. pyPLUTO/h_pypluto.py +84 -0
  15. pyPLUTO/image.py +302 -0
  16. pyPLUTO/imagefuncs/colorbar.py +240 -0
  17. pyPLUTO/imagefuncs/contour.py +254 -0
  18. pyPLUTO/imagefuncs/create_axes.py +464 -0
  19. pyPLUTO/imagefuncs/display.py +306 -0
  20. pyPLUTO/imagefuncs/figure.py +395 -0
  21. pyPLUTO/imagefuncs/imagetools.py +487 -0
  22. pyPLUTO/imagefuncs/interactive.py +403 -0
  23. pyPLUTO/imagefuncs/legend.py +250 -0
  24. pyPLUTO/imagefuncs/plot.py +311 -0
  25. pyPLUTO/imagefuncs/range.py +242 -0
  26. pyPLUTO/imagefuncs/scatter.py +270 -0
  27. pyPLUTO/imagefuncs/set_axis.py +497 -0
  28. pyPLUTO/imagefuncs/streamplot.py +297 -0
  29. pyPLUTO/imagefuncs/zoom.py +428 -0
  30. pyPLUTO/imagemixin.py +259 -0
  31. pyPLUTO/imagestate.py +45 -0
  32. pyPLUTO/load.py +447 -0
  33. pyPLUTO/loadfuncs/baseloadtools.py +71 -0
  34. pyPLUTO/loadfuncs/codeselection.py +48 -0
  35. pyPLUTO/loadfuncs/defpluto.py +123 -0
  36. pyPLUTO/loadfuncs/descriptor.py +102 -0
  37. pyPLUTO/loadfuncs/findfiles.py +182 -0
  38. pyPLUTO/loadfuncs/findformat.py +245 -0
  39. pyPLUTO/loadfuncs/initload.py +203 -0
  40. pyPLUTO/loadfuncs/loadvars.py +227 -0
  41. pyPLUTO/loadfuncs/offsetdata.py +87 -0
  42. pyPLUTO/loadfuncs/offsetfluid.py +408 -0
  43. pyPLUTO/loadfuncs/read_files.py +213 -0
  44. pyPLUTO/loadfuncs/readdata.py +619 -0
  45. pyPLUTO/loadfuncs/readdata_old.py +567 -0
  46. pyPLUTO/loadfuncs/readdefplini.py +101 -0
  47. pyPLUTO/loadfuncs/readfluid.py +479 -0
  48. pyPLUTO/loadfuncs/readformat.py +277 -0
  49. pyPLUTO/loadfuncs/readgridalone.py +224 -0
  50. pyPLUTO/loadfuncs/readgridfile.py +255 -0
  51. pyPLUTO/loadfuncs/readgridout.py +451 -0
  52. pyPLUTO/loadfuncs/readpart.py +419 -0
  53. pyPLUTO/loadfuncs/readtab.py +105 -0
  54. pyPLUTO/loadfuncs/write_files.py +283 -0
  55. pyPLUTO/loadmixin.py +419 -0
  56. pyPLUTO/loadpart.py +233 -0
  57. pyPLUTO/loadstate.py +68 -0
  58. pyPLUTO/newload.py +81 -0
  59. pyPLUTO/pytools.py +145 -0
  60. pyPLUTO/toolfuncs/findlines.py +551 -0
  61. pyPLUTO/toolfuncs/fourier.py +149 -0
  62. pyPLUTO/toolfuncs/nabla.py +676 -0
  63. pyPLUTO/toolfuncs/parttools.py +152 -0
  64. pyPLUTO/toolfuncs/transform.py +638 -0
  65. pyPLUTO/utils/annotator.py +27 -0
  66. pyPLUTO/utils/inspector.py +145 -0
  67. pyPLUTO/utils/make_docstrings.py +3 -0
  68. py_pluto-1.1.4.dist-info/METADATA +218 -0
  69. py_pluto-1.1.4.dist-info/RECORD +73 -0
  70. py_pluto-1.1.4.dist-info/WHEEL +5 -0
  71. py_pluto-1.1.4.dist-info/entry_points.txt +2 -0
  72. py_pluto-1.1.4.dist-info/licenses/LICENSE +27 -0
  73. py_pluto-1.1.4.dist-info/top_level.txt +1 -0
@@ -0,0 +1,464 @@
1
+ """Module to create axes in the image class."""
2
+
3
+ import copy
4
+ import warnings
5
+ from itertools import islice
6
+ from typing import Any
7
+
8
+ import matplotlib.pyplot as plt
9
+ import numpy as np
10
+ from matplotlib.axes import Axes
11
+
12
+ from pyPLUTO.imagemixin import ImageMixin
13
+ from pyPLUTO.imagestate import ImageState
14
+ from pyPLUTO.utils.inspector import track_kwargs
15
+
16
+ defaults: dict[str, Any] = {
17
+ "left": 0.125,
18
+ "right": 0.9,
19
+ "top": 0.9,
20
+ "bottom": 0.1,
21
+ "hspace": [],
22
+ "wspace": [],
23
+ "hratio": [1.0],
24
+ "wratio": [1.0],
25
+ }
26
+
27
+
28
+ class CreateAxesManager(ImageMixin):
29
+ """Class to manage the creation of axes in the image.
30
+
31
+ This class provides methods to create axes in the image class. It allows
32
+ for customization of the axes' position, spacing, projection, and other
33
+ properties.
34
+ """
35
+
36
+ exposed_methods = ("create_axes",)
37
+
38
+ def __init__(self, state: ImageState) -> None:
39
+ """Initialize the CreateAxesManager class."""
40
+ self.state: ImageState = state
41
+
42
+ @track_kwargs(extra_keys=set(defaults.keys()))
43
+ def create_axes(
44
+ self, ncol: int = 1, nrow: int = 1, check: bool = True, **kwargs: Any
45
+ ) -> Axes | list[Axes]:
46
+ """Creation of a set of axes using add_subplot from matplotlib.
47
+
48
+ If additional parameters (like the figure limits or the spacing)
49
+ are given, the plots are located using set_position.
50
+ The spacing and the ratio between the plots can be given by hand.
51
+ In case only few custom options are given, the code computes the rest
52
+ (but gives a small warning); in case no custom option is given, the axes
53
+ are located through the standard methods of matplotlib.
54
+
55
+ If more axes are created in the figure, the list of all axes is
56
+ returned, otherwise the single axis is returned.
57
+
58
+ Returns
59
+ -------
60
+ - The list of axes (if more axes are in the figure) or the axis
61
+ (if only one axis is present)
62
+
63
+ Parameters
64
+ ----------
65
+ - bottom: float, default 0.1
66
+ The space from the bottom border to the last row of plots.
67
+ - figsize: [float, float], default [6*sqrt(ncol),5*sqrt(nrow)]
68
+ Sets the figure size. The default value is computed from the number
69
+ of rows and columns.
70
+ - fontsize: float, default 17.0
71
+ Sets the fontsize for all the axes.
72
+ - hratio: [float], default [1.0]
73
+ Ratio between the rows of the plot. The default is that every plot
74
+ row has the same height.
75
+ - hspace: [float], default []
76
+ The space between plot rows (in figure units). If not enough or
77
+ too many spaces are considered, the program will remove the excess
78
+ and fill the lacks with [0.1].
79
+ - left: float, default 0.125
80
+ The space from the left border to the leftmost column of plots.
81
+ - ncol: int, default 1
82
+ The number of columns of subplots.
83
+ - nrow: int, default 1
84
+ The number of rows of subplots.
85
+ - proj: str, default None
86
+ Custom projection for the plot (e.g. 3D). Recommended only if
87
+ needed.
88
+ WARNING: pyPLUTO does not support 3D plotting for now, only 3D axes.
89
+ The 3D plot feature will be available in future releases.
90
+ - right: float, default 0.9
91
+ The space from the right border to the rightmost column of plots.
92
+ - sharex: bool | str | Matplotlib axis, default False
93
+ Enables/disables the sharing of the x-axis between the subplots.
94
+ - sharey: bool | str | Matplotlib axis, default False
95
+ Enables/disables the sharing of the y-axis between the subplots.
96
+ - suptitle: str, default None
97
+ Creates a figure title over all the subplots.
98
+ - tight: bool, default True
99
+ Enables/disables tight layout options for the figure. In case of a
100
+ highly customized plot (e.g. ratios or space between rows and
101
+ columns) the option is set by default to False since that option
102
+ would not be available for standard matplotlib functions.
103
+ - top: float, default 0.9
104
+ The space from the top border to the first row of plots.
105
+ - wratio: [float], default [1.0]
106
+ Ratio between the columns of the plot. The default is that every
107
+ plot column has the same width.
108
+ - wspace: [float], default []
109
+ The space between plot columns (in figure units). If not enough or
110
+ too many spaces are considered, the program will remove the excess
111
+ and fill the lacks with [0.1].
112
+
113
+ ----
114
+
115
+ Examples
116
+ --------
117
+ - Example #1: create a simple grid of 2 columns and 2 rows on a new
118
+ figure
119
+
120
+ >>> import pyPLUTO as pp
121
+ >>> I = pp.Image()
122
+ >>> ax = I.create_axes(ncol=2, nrow=2)
123
+
124
+ - Example #2: create a grid of 2 columns with the first one having half
125
+ the width of the second one
126
+
127
+ >>> import pyPLUTO as pp
128
+ >>> I = pp.Image()
129
+ >>> ax = I.create_axes(ncol=2, wratio=[0.5, 1])
130
+
131
+ - Example #3: create a grid of 2 rows with a lot of blank space between
132
+ them
133
+
134
+ >>> import pyPLUTO as pp
135
+ >>> I = pp.Image()
136
+ >>> ax = I.create_axes(nrow=2, hspace=[0.5])
137
+
138
+ - Example #4: create a 2x2 grid with a fifth image on the right side
139
+
140
+ >>> import pyPLUTO as pp
141
+ >>> I = pp.Image()
142
+ >>> ax = I.create_axes(ncol=2, nrow=2, right=0.7)
143
+ >>> ax = I.create_axes(left=0.75)
144
+
145
+ """
146
+ kwargs.pop("check", check)
147
+
148
+ # Change fontsize if requested
149
+ if "fontsize" in kwargs:
150
+ plt.rcParams.update({"font.size": kwargs["fontsize"]})
151
+
152
+ custom_plot = bool(defaults.keys() & kwargs.keys())
153
+
154
+ if custom_plot:
155
+ kwargs["tight"] = False
156
+ filtered_kwargs = {
157
+ key: kwargs.get(key, value) for key, value in defaults.items()
158
+ }
159
+ wplot, hplot = self._set_custom_axes(filtered_kwargs, nrow, ncol)
160
+ else:
161
+ wplot, hplot = None, None
162
+
163
+ # Set figure size
164
+ if self.fig is None:
165
+ raise ValueError(
166
+ "You need to create a figure before creating axes."
167
+ )
168
+
169
+ if figsize := kwargs.get("figsize"):
170
+ self.fig.set_size_inches(*figsize)
171
+ self.figsize = figsize
172
+ elif not (custom_plot or self.set_size):
173
+ self.fig.set_size_inches(6 * np.sqrt(ncol), 5 * np.sqrt(nrow))
174
+
175
+ # Set the projection if requested
176
+ proj = kwargs.get("proj")
177
+
178
+ # Set sharex and sharey
179
+ sharex: bool | str | Axes | int | None = kwargs.get("sharex")
180
+ sharey: bool | str | Axes | int | None = kwargs.get("sharey")
181
+
182
+ for i in range(ncol * nrow):
183
+ sharex_ref = self._check_shareaxis(i, sharex)
184
+ # Interpret True as: share with the first axis
185
+ # if sharex is True:
186
+ # sharex_ref = self.ax[0] if i > 0 else None
187
+ # elif isinstance(sharex, int):
188
+ # sharex_ref = self.ax[sharex]
189
+ # else:
190
+ # sharex_ref = sharex # None or an Axes reference
191
+
192
+ # Same for sharey
193
+ sharey_ref = self._check_shareaxis(i, sharey)
194
+ # if sharey is True:
195
+ # sharey_ref = self.ax[0] if i > 0 else None
196
+ # elif isinstance(sharey, int):
197
+ # sharey_ref = self.ax[sharey]
198
+ # else:
199
+ # sharey_ref = sharey
200
+
201
+ self.add_ax(
202
+ axis := self.fig.add_subplot(
203
+ nrow + self.nrow0,
204
+ ncol + self.ncol0,
205
+ i + 1,
206
+ projection=proj,
207
+ sharex=sharex_ref,
208
+ sharey=sharey_ref,
209
+ ),
210
+ len(self.ax),
211
+ )
212
+ self.ax.append(axis)
213
+
214
+ # Compute row and column
215
+ row = int(i / ncol)
216
+ col = int(i % ncol)
217
+
218
+ # Set position if custom axes
219
+ if wplot is not None and hplot is not None:
220
+ self.ax[-1].set_position(
221
+ pos=(
222
+ wplot[col][0],
223
+ hplot[row][0],
224
+ wplot[col][1],
225
+ hplot[row][1],
226
+ )
227
+ )
228
+
229
+ # Updates rows and columns
230
+ self.nrow0 = self.nrow0 + nrow
231
+ self.ncol0 = self.ncol0 + ncol
232
+
233
+ # Set figure title if requested
234
+ if "suptitle" in kwargs:
235
+ self.fig.suptitle(kwargs["suptitle"])
236
+
237
+ # Tight layout (depending on the subplot creation)
238
+ self.tight = kwargs.get("tight", self.tight)
239
+ self.fig.set_layout_engine(None if not self.tight else "tight")
240
+
241
+ ret_ax = self.ax[0] if len(self.ax) == 1 else self.ax
242
+
243
+ # if not isinstance(ret_ax, list | Axes):
244
+ # raise TypeError("The returned axis is neither a list nor an Axes.")
245
+
246
+ return ret_ax
247
+
248
+ def _set_custom_axes(
249
+ self, custom: dict[str, Any], nrow: int, ncol: int
250
+ ) -> tuple[list[list[float]], list[list[float]]]:
251
+ """Set the axes position and spacing according to the parameters.
252
+
253
+ Returns
254
+ -------
255
+ - wplot: list[list[float]]
256
+ List of the left and right position of the axes.
257
+ - hplot: list[list[float]]
258
+ List of the top and bottom position of the axes.
259
+
260
+ Parameters
261
+ ----------
262
+ - custom: dict[str, Any]
263
+ Dictionary with the custom parameters for the axes.
264
+ - nrow: int
265
+ Number of rows in the axes.
266
+ - ncol: int
267
+ Number of columns in the axes.
268
+
269
+ """
270
+ hspace, hratio = self._check_rowcol(
271
+ custom["hratio"], custom["hspace"], nrow, "rows"
272
+ )
273
+ wspace, wratio = self._check_rowcol(
274
+ custom["wratio"], custom["wspace"], ncol, "cols"
275
+ )
276
+
277
+ hsize = custom["top"] - custom["bottom"] - sum(hspace)
278
+ wsize = custom["right"] - custom["left"] - sum(wspace)
279
+ htot, wtot = sum(hratio), sum(wratio)
280
+ ll, tt = custom["left"], custom["top"]
281
+ hplot, wplot = [], []
282
+
283
+ # Computes left, right of every ax
284
+ for i in islice(range(ncol), ncol - 1):
285
+ rr = wsize * wratio[i] / wtot
286
+ wplot.append([ll, rr])
287
+ ll += rr + wspace[i]
288
+
289
+ # Computes top, bottom of every ax
290
+ for i in islice(range(nrow), nrow - 1):
291
+ bb = tt - hsize * hratio[i] / htot
292
+ hplot.append([bb, tt - bb])
293
+ tt = bb - hspace[i]
294
+
295
+ # Append the last items without extra space
296
+ rr = wsize * wratio[ncol - 1] / wtot
297
+ wplot.append([ll, rr])
298
+
299
+ bb = tt - hsize * hratio[nrow - 1] / htot
300
+ hplot.append([bb, tt - bb])
301
+ return wplot, hplot
302
+
303
+ def _check_rowcol(
304
+ self,
305
+ ratio: list[float],
306
+ space: float | list[float | int],
307
+ length: int,
308
+ func: str,
309
+ ) -> tuple[list[float | int], list[float | int]]:
310
+ """Check the width and spacing of the plots on a single row or column.
311
+
312
+ Returns
313
+ -------
314
+ - space: list[float]
315
+ the space between the rows or columns
316
+ - ratio: list[float]
317
+ the ratio of the rows or columns
318
+
319
+ Parameters
320
+ ----------
321
+ - ratio: list[float]
322
+ the ratio of the rows or columns
323
+ - space: list[float]
324
+ the space between the rows or columns
325
+ - length: int
326
+ the number of rows or columns in the single row or column
327
+ - func: str
328
+ the function to check (rows or cols)
329
+
330
+ ----
331
+
332
+ Examples
333
+ --------
334
+ - Example #1: ratio and space are given correctly (rows)
335
+
336
+ >>> _check_rowcol([1, 2, 3], [0.1, 0.2], 3, "rows")
337
+
338
+ - Example #2: ratio and space are given incorrectly (rows) (warning)
339
+
340
+ >>> _check_rowcol([], 0.1, 3, "rows")
341
+
342
+ - Example #3: ratio and space are given correctly (cols)
343
+
344
+ >>> _check_rowcol([1, 2, 3], [0.1, 0.2], 3, "cols")
345
+
346
+ """
347
+ rat = {"rows": "hratio", "cols": "wratio"}
348
+ spc = {"rows": "hspace", "cols": "wspace"}
349
+
350
+ # Check if space is a list
351
+ newspace = space if isinstance(space, list) else [space]
352
+ space = space if isinstance(space, list) else newspace * (length - 1)
353
+
354
+ # Fill the lists with the default values
355
+ ratio = ratio + [1.0] * (length - len(ratio))
356
+ space = space + [0.1] * (length - len(space) - 1)
357
+ print(ratio, length)
358
+
359
+ # Check if the lists have the correct length
360
+ if len(ratio) != length:
361
+ warn = f"WARNING! {rat[func]} has wrong length!"
362
+ warnings.warn(warn, UserWarning, stacklevel=2)
363
+ if len(space) + 1 != length:
364
+ warn = f"WARNING! {spc[func]} has wrong length!"
365
+ warnings.warn(warn, UserWarning, stacklevel=2)
366
+
367
+ # End of the function. Return the lists
368
+ return space[: length - 1], ratio[:length]
369
+
370
+ def add_ax(self, ax: Axes, i: int) -> None:
371
+ """Add the axhes properties to the class info variables.
372
+
373
+ The corresponding axis is appended to the list of axes.
374
+
375
+ Returns
376
+ -------
377
+ - None
378
+
379
+ Parameters
380
+ ----------
381
+ - ax (not optional): ax
382
+ The axis to be added.
383
+ - i (not optional): int
384
+ The index of the axis in the list.
385
+
386
+ ----
387
+
388
+ Examples
389
+ --------
390
+ - Example #1: Add the axis to the class info variables
391
+
392
+ >>> _add_ax(ax, i)
393
+
394
+ """
395
+ ax_pars = {
396
+ # "ax": ax,
397
+ "legpos": None,
398
+ "legpar": [self.fontsize, 1, 2, 0.8, 0.8],
399
+ "nline": 0,
400
+ "ntext": None,
401
+ "setax": 0,
402
+ "setay": 0,
403
+ "shade": "auto",
404
+ "tickspar": 0,
405
+ "xscale": "linear",
406
+ "yscale": "linear",
407
+ "vlims": [],
408
+ }
409
+
410
+ # Append the axis to the list of axes
411
+ for attr, default in ax_pars.items():
412
+ getattr(self, attr).append(copy.copy(default))
413
+
414
+ # Position the axis index in the middle of the axis
415
+ ax.annotate(str(i), (0.47, 0.47), xycoords="axes fraction")
416
+
417
+ def _check_shareaxis(
418
+ self, i: int, share: bool | str | Axes | int | None
419
+ ) -> Axes | str | None:
420
+ """Check the sharing of the x or y axis.
421
+
422
+ Returns
423
+ -------
424
+ - share_ref: Axes | str | None
425
+ The reference axis for sharing.
426
+
427
+ Parameters
428
+ ----------
429
+ - i: int
430
+ The index of the current axis.
431
+ - share: bool | str | Axes | int | None
432
+ The sharing option.
433
+
434
+ ----
435
+
436
+ Examples
437
+ --------
438
+ - Example #1: share is True
439
+
440
+ >>> _check_shareaxis(0, True)
441
+
442
+ - Example #2: share is False
443
+
444
+ >>> _check_shareaxis(0, False)
445
+
446
+ - Example #3: share is a string
447
+
448
+ >>> _check_shareaxis(0, "left")
449
+
450
+ - Example #4: share is an axis
451
+
452
+ >>> _check_shareaxis(0, ax)
453
+
454
+ """
455
+ if share is True:
456
+ share_ref = self.ax[0] if i > 0 else None
457
+ elif isinstance(share, int):
458
+ share_ref = self.ax[share]
459
+ else:
460
+ share_ref = share
461
+
462
+ return share_ref
463
+
464
+ # End of the function