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
pyPLUTO/imagestate.py ADDED
@@ -0,0 +1,45 @@
1
+ """Module that contains the ImageState class."""
2
+
3
+ from dataclasses import dataclass, field
4
+ from typing import Any
5
+
6
+ from matplotlib.axes import Axes
7
+ from matplotlib.figure import Figure
8
+
9
+
10
+ @dataclass
11
+ class ImageState:
12
+ """Class that stores the state of the Image class.
13
+
14
+ Its purpose is to keep track of the current state of the image, such as the
15
+ figure, axes, and other properties and update the key attributes through all
16
+ the different classes that handle the plotting and display of the image at
17
+ runtime.
18
+ """
19
+
20
+ # pylint: disable=too-many-instance-attributes
21
+
22
+ ax: list[Axes] = field(default_factory=list)
23
+ color: list[str] = field(default_factory=list)
24
+ dictcol: dict[int, str] = field(default_factory=dict)
25
+ fig: Figure | None = None
26
+ figsize: list[float] = field(default_factory=lambda: [8.0, 5.0])
27
+ fontsize: int = 17
28
+ LaTeX: bool | str = True
29
+ legpar: list[list[float]] = field(default_factory=list)
30
+ legpos: list[int | str | None] = field(default_factory=list)
31
+ ncol0: int = 0
32
+ nline: list[int] = field(default_factory=list)
33
+ nrow0: int = 0
34
+ ntext: list[Any | None] = field(default_factory=list)
35
+ nwin: int = 1
36
+ setax: list[Any | int] = field(default_factory=list)
37
+ setay: list[Any | int] = field(default_factory=list)
38
+ set_size: bool = False
39
+ shade: list[str] = field(default_factory=list)
40
+ style: str = "default"
41
+ tickspar: list[Any | int] = field(default_factory=list)
42
+ tight: bool = True
43
+ vlims: list[list[float]] = field(default_factory=list)
44
+ xscale: list[str] = field(default_factory=list)
45
+ yscale: list[str] = field(default_factory=list)
pyPLUTO/load.py ADDED
@@ -0,0 +1,447 @@
1
+ """
2
+ Load the PLUTO data files.
3
+
4
+ The Load class loads the data (fluid) from the output files.
5
+ """
6
+
7
+ from pathlib import Path
8
+ from typing import Any
9
+
10
+ import numpy as np
11
+ from numpy.typing import NDArray
12
+
13
+ from pyPLUTO.h_pypluto import check_par
14
+
15
+
16
+ class Load:
17
+ """The Load class loads the data (fluid) from the output files.
18
+
19
+ The initialization corresponds to the loading, if wanted, of one or more
20
+ datafiles for the fluid. The data are loaded in a memory mapped numpy
21
+ multidimensional array. Such approach does not load the full data
22
+ until needed. Basic operations (i.e. no numpy) are possible, as well
23
+ as slicing the arrays, without fully loading the data.
24
+
25
+ Returns
26
+ -------
27
+ - None
28
+
29
+ Parameters
30
+ ----------
31
+ - alone: bool | None, default False
32
+ If the files are standalone. If False, the code will look for the
33
+ grid file in the folder. If True, the code will look for the grid
34
+ information within the data files. Should be used only for non-binary
35
+ files.
36
+ - code: str | None, default None
37
+ The code from which the data are loaded. If None, the code assumes
38
+ PLUTO/gPLUTO. If a different code is provided, the corresponding
39
+ loading method is used (if implemented).
40
+ - datatype: str | None, default None
41
+ The format of the data file. If not specified, the code will look for
42
+ the format from the list of possible formats. HDF5 (AMR) formats have
43
+ not been implemented yet.
44
+ - endian: str | None, default None
45
+ Endianess of the datafiles. Should be used only if specific
46
+ architectures are used, since the code computes it by itself. Valid
47
+ values are 'big' and 'little' (or '<' and '>').
48
+ - full3d: bool, default True
49
+ If disabled, the 3D meshgrids for the grid in non-cartesian coordinates
50
+ are not used. Instead, a combination of an external loop and2D meshgrid
51
+ is employed. The aim is to allow for cartesian meshes from non-cartesian
52
+ geometries without saturating the computer memory (suited for laptops).
53
+ - level: int, default 0
54
+ The refinement level of the grid. Should be used only if the grid is
55
+ refined through AMR.
56
+ - multiple: bool, default False
57
+ If the files are multiple. If False, the code will look for the single
58
+ files, otherwise for the multiple files each corresponding to the loaded
59
+ variables. Should be used only if both single files and multiple files
60
+ are present in the same format for the same datatype.
61
+ - nout: int | str | list | None, default 'last'
62
+ The files to be loaded. Possible choices are int values (which
63
+ correspond to the number of the output file), strings ('last', which
64
+ corresponds to the last file, 'all', which corresponds to all files) or
65
+ a list of the aforementioned types. Note that the 'all' value should be
66
+ used carefully, e.g. only when the data need to be shown interactively.
67
+ - path: str, default './'
68
+ The path of the folder where the files should be loaded.
69
+ - text: bool, default True
70
+ If True, the folder and output are printed. In case the user needs a
71
+ more detailed information of the structure and attributes loaded from
72
+ the class, the __str__ method provides a easy display of all the
73
+ important information.
74
+ - vars: str | list | bool | None, default True
75
+ The variables to be loaded. The default value, True, corresponds to all
76
+ the variables.
77
+
78
+ ----
79
+
80
+ Examples
81
+ --------
82
+ - Example #1: Load the data from the default folder and output
83
+
84
+ >>> D = pp.Load()
85
+ Loading folder ./, output [0]
86
+
87
+ - Example #2: Load the data from the default folder but output 0
88
+
89
+ >>> D = pp.Load(nout=0)
90
+ Loading folder ./, output [0]
91
+
92
+ - Example #3: Load the data from the default folder but last output is
93
+ specified
94
+
95
+ >>> D = pp.Load(nout="last")
96
+ Loading folder ./, output [1]
97
+
98
+ - Example #4: Load the data from the default folder and all outputs
99
+
100
+ >>> D = pp.Load(nout="all")
101
+ Loading folder ./, output [0, 1, 2, 3, 4]
102
+
103
+ - Example #5: Load the data from the default folder and multiple
104
+ selected outputs
105
+
106
+ >>> D = pp.Load(nout=[0, 1, 2])
107
+ Loading folder ./, output [0, 1, 2]
108
+
109
+ - Example #6: Load the data from the default folder and multiple selected
110
+ outputs and variables
111
+
112
+ >>> D = pp.Load(nout=[0, 1, 2], vars=["rho", "vel1"])
113
+ Loading folder ./, output [0, 1, 2]
114
+
115
+ - Example #7: Load the data from the default folder, multiple selected
116
+ outputs and variables, without text
117
+
118
+ >>> D = pp.Load(nout=[0, 1, 2], vars=["rho", "vel1"], text=False)
119
+
120
+ - Example #8: Load the data from the default format with selected output
121
+ and format
122
+
123
+ >>> D = pp.Load(data="vtk", nout=0)
124
+ Loading folder ./, output [0]
125
+
126
+ - Example #9: Load the data from the default folder with selected output,
127
+ variables and format
128
+
129
+ >>> D = pp.Load(data="vtk", nout=0, vars=["rho", "vel1"])
130
+ Loading folder ./, output [0]
131
+
132
+ - Example #10: Load the data from a specific folder with selected output
133
+
134
+ >>> D = pp.Load(path="./data/", nout=0)
135
+ Loading folder ./data/, output [0]
136
+
137
+ """
138
+
139
+ def __init__(
140
+ self,
141
+ nout: int | str | list[int | str] | None = "last",
142
+ path: str | Path = "./",
143
+ datatype: str | None = None,
144
+ vars: str | list[str] | bool | None = True,
145
+ text: bool = True,
146
+ check: bool = True,
147
+ **kwargs: Any,
148
+ ) -> None:
149
+ # Check parameters
150
+ param = {
151
+ "alone",
152
+ "code",
153
+ "read_defh",
154
+ "endian",
155
+ "full3d",
156
+ "level",
157
+ "multiple",
158
+ "fastvtk",
159
+ }
160
+ if check is True:
161
+ check_par(param, "__init__", **kwargs)
162
+
163
+ """
164
+ # Load PyPLUTO for different codes
165
+ code = kwargs.get("code")
166
+ codedict = {"echo": self.echo_load}
167
+ # If not code is provided (or the code is PLUTO/gPLUTO) just skip
168
+ if not code or code.lower() in {"pluto", "gpluto"}:
169
+ pass
170
+ elif code.lower() in codedict:
171
+ init = f"Loading data with alternative method using code: {code}"
172
+ if text is True:
173
+ print(init)
174
+ codedict[code.lower()](nout, path, vars)
175
+ if not isinstance(self.nout, int):
176
+ self.nout = self.nout.astype(int)
177
+ if text is True:
178
+ print(f"Load: folder {path}, output {self.nout}")
179
+ return
180
+ else:
181
+ raise NotImplementedError(f"{code} loading is not implemented!")
182
+ """
183
+
184
+ # Check if the user wants to load the data
185
+ if nout is None:
186
+ print("No output is loaded!")
187
+ return
188
+
189
+ # Initialization or declaration of variables (used in this file)
190
+ self.nout: NDArray # Output to be loaded
191
+ self._d_end: dict[str | None, str | None] # Endianess dictionary
192
+ self._multiple: bool # Bool for single or multiple files
193
+ self._alone: bool | None = None # Bool for standalone files
194
+ self._info: bool = True # Bool for info (linked to alone)
195
+ self._d_vars: dict = {} # The dictionary of variables
196
+ self.level: int = kwargs.get("level", 0) # The level for AMR files
197
+
198
+ # Initialization or declaration of variables (used in other files)
199
+ self.pathdir: Path # Path to the simulation directory
200
+ self.format: str | None = None # The format of the files to be loaded
201
+ self.outlist: NDArray # The list of outputs to be loaded
202
+ self.timelist: NDArray # The list of times to be loaded
203
+ self.ntime: NDArray # The time array
204
+ self.set_vars: set[str] # The set of variables to be loaded
205
+ self.set_outs: set[int] # The set of outputs to be loaded
206
+ self.geom: str # The geometry of the simulation
207
+ self.dim: int # The dimension of the simulation
208
+ self.nshp: int | tuple[int, ...] # The shape of the grid
209
+ self.nfile_lp: int | None = None # File number for the lp methods
210
+
211
+ self._charsize: int # The data size in the files
212
+ self._lennout: int # The number of outputs to be loaded
213
+ self._d_info: dict[str, Any] # Info dictionary
214
+ self._matching_files: list[str] # The list of files to be loaded
215
+ self._pathgrid: Path # Path to the grid file
216
+ self._pathdata: Path | None = (
217
+ None # Path to the data files to be loaded
218
+ )
219
+ self._filepath: Path # The filepath to be loaded
220
+ self._load_vars: list[str] # The list of variables to be loaded
221
+ self._offset: dict[str, int] # The offset of the variables
222
+ self._shape: dict[str, tuple[int, ...]] # The shape of the variables
223
+ self._vardim: list[int] # The dimension of the variables
224
+ self._dictdim: dict # The dictionary of dimensions
225
+ self._fastvtk: bool = kwargs.get(
226
+ "fastvtk", True
227
+ ) # Bool for fast vtk loading
228
+
229
+ # Declaration of the grid variables
230
+ self.x1: NDArray
231
+ self.x2: NDArray
232
+ self.x3: NDArray # centered grid
233
+ self.x1r: NDArray
234
+ self.x2r: NDArray
235
+ self.x3r: NDArray # staggered grid
236
+ self.x1c: NDArray
237
+ self.x2c: NDArray # cartesian centered grid
238
+ self.x1rc: NDArray
239
+ self.x2rc: NDArray # cartesian staggered grid
240
+ self.dx1: NDArray
241
+ self.dx2: NDArray
242
+ self.dx3: NDArray # cell size
243
+ self.nx1: int
244
+ self.nx2: int
245
+ self.nx3: int # number of cells
246
+ self.gridsize: int # total number of cells
247
+ self.gridlist3: list[str]
248
+ self.x1p: NDArray
249
+ self.x2p: NDArray
250
+ self.x1rp: NDArray
251
+ self.x2rp: NDArray
252
+
253
+ self._gridsize_st1: int
254
+ self._nshp_st1: NDArray
255
+ self._gridsize_st2: int
256
+ self._nshp_st2: NDArray
257
+ self._gridsize_st3: int
258
+ self._nshp_st3: NDArray
259
+ self._full3d: bool = kwargs.get("full3d", False)
260
+
261
+ _nout_out: int | list[int] # Output to be printed
262
+
263
+ # Check the input endianess
264
+ self._d_end = {
265
+ "big": ">",
266
+ "little": "<",
267
+ ">": ">",
268
+ "<": "<",
269
+ None: None,
270
+ }
271
+
272
+ if (endian := kwargs.get("endian")) not in self._d_end.keys():
273
+ error = f"Invalid endianess. Valid values are {self._d_end.keys()}"
274
+ raise ValueError(error)
275
+
276
+ # Check the input multiple
277
+ multiple = kwargs.get("multiple", False)
278
+ if not isinstance(multiple, bool):
279
+ raise TypeError("Invalid data type. 'multiple' must be a boolean.")
280
+ else:
281
+ self._multiple = multiple
282
+
283
+ # Check if the path is an existing directory
284
+ self._check_pathformat(path)
285
+
286
+ # Find the format of the data files
287
+ self._find_format(datatype, kwargs.get("alone"))
288
+
289
+ # Find relevant information without opening the files (e.g.
290
+ # the number of files to be loaded) or opening the *.out files
291
+ if self._alone is True:
292
+ self._findfiles(nout)
293
+ else:
294
+ self._read_outfile(nout, endian)
295
+
296
+ # For every output load the desired variables
297
+ for i, exout in enumerate(self.nout):
298
+ self._load_variables(vars, i, exout, endian)
299
+
300
+ # Assign the variables to the class
301
+ for key in self._d_vars:
302
+ setattr(self, key, self._d_vars[key])
303
+
304
+ # Transpose nshp (to match with variables)
305
+ # try:
306
+ # self.nshp = self.nshp[::-1] if self.dim > 1 else self.nshp
307
+ # except ValueError:
308
+ # pass
309
+
310
+ # Convert ntime if only one number of a list
311
+ if isinstance(self.ntime, np.ndarray) and len(self.ntime) == 1:
312
+ self.ntime = self.ntime[0]
313
+
314
+ # Print loaded folder and output
315
+ if text:
316
+ _nout_out = (
317
+ self.nout[0]
318
+ if len(self.nout) == 1
319
+ else [int(x) for x in self.nout]
320
+ )
321
+ print(f"Load: folder {path}, output {_nout_out}")
322
+
323
+ # Try to read the file definitions.h
324
+ defh = kwargs.get("defh")
325
+ if defh is not False:
326
+ pathdefh = self.pathdir / "definitions.h"
327
+ defhfile = "definitions.hpp"
328
+ if not pathdefh.exists():
329
+ pathdefh = self.pathdir / "definitions.hpp"
330
+ defhfile = "definitions.h"
331
+ try:
332
+ self.defh = self._read_defh(pathdefh)
333
+ except FileNotFoundError:
334
+ print(f"No {defhfile} is read!") if defh is True else ...
335
+
336
+ # Try to read the file pluto.ini
337
+ plini = kwargs.get("plini")
338
+ if plini is not False:
339
+ pathplini = self.pathdir / "pluto.ini"
340
+ try:
341
+ self.plini = self._read_plini(pathplini)
342
+ except FileNotFoundError:
343
+ print("No pluto.ini is read!") if plini is True else ...
344
+ return
345
+
346
+ def __str__(self) -> str:
347
+ text3 = f" - Projections {['x1c', 'x2c', 'x1rc', 'x2rc']}\n"
348
+ text3 = text3 if self.geom != "CARTESIAN" else ""
349
+
350
+ text = f"""
351
+ Load class.
352
+ It loads the data.
353
+
354
+ File properties:
355
+ - Current path loaded (pathdir) {self.pathdir}
356
+ - Format loaded (format) {self.format}
357
+
358
+ Simulation properties
359
+ - Dimensions (dim) {self.dim}
360
+ - Geometry (geom) {self.geom}
361
+ - Grid size (gridsize) {self.gridsize}
362
+ - Grid shape (nshp) {self.nshp}
363
+ - Output loaded (nout) {self.nout}
364
+ - Time loaded (ntime) {self.ntime}
365
+
366
+ Public attributes available:
367
+ - Number of cells in each direction {["nx1", "nx2", "nx3"]}
368
+ - Grid values (cell center) {["x1", "x2", "x3"]}
369
+ - Grid values (face center) {["x1r", "x2r", "x3r"]}
370
+ - Cells size {["dx1", "dx2", "dx3"]}
371
+ - Time attributes {["outlist", "timelist"]}\n{text3}
372
+ Variables available:
373
+ {self._d_info["varslist"][0]}
374
+ Variables loaded:
375
+ {self._load_vars}
376
+
377
+ Public methods available:
378
+
379
+ - slices
380
+ - cartesian_vector
381
+ - reshape_cartesian
382
+ - write_file
383
+ - fourier
384
+ - nabla
385
+ - find_contour
386
+ - find_fieldlines
387
+ - vector_field
388
+
389
+ Please refrain from using "private" methods and attributes.
390
+ """
391
+ return text
392
+
393
+ def __getattr__(self, name):
394
+ try:
395
+ return object.__getattribute__(self, f"_{name}")
396
+ except AttributeError:
397
+ raise AttributeError(
398
+ f"'Load' object has no attribute '{name}'"
399
+ ) from None
400
+
401
+ from .amr import _DataScanHDF5, _inspect_hdf5
402
+
403
+ """
404
+ from .codes.echo_load import (
405
+ _echo_load_grid,
406
+ _echo_load_vars,
407
+ _echo_set_grid_dims,
408
+ echo_load,
409
+ )
410
+ """
411
+
412
+ from .loadfuncs.defpluto import _read_defh, _read_plini
413
+ from .loadfuncs.read_files import _read_dat, _read_h5, read_file
414
+ from .loadfuncs.readdata_old import (
415
+ _assign_var,
416
+ _check_nout,
417
+ _findfiles,
418
+ _init_vardict,
419
+ _load_variables,
420
+ )
421
+ from .loadfuncs.readfluid import (
422
+ _compute_offset,
423
+ _inspect_h5,
424
+ _inspect_vtk,
425
+ _offset_bin,
426
+ _read_tabfile,
427
+ )
428
+ from .loadfuncs.readformat import _check_pathformat, _find_format
429
+ from .loadfuncs.readgridout import (
430
+ _read_grid_h5,
431
+ _read_grid_vtk,
432
+ _read_gridfile,
433
+ _read_outfile,
434
+ _split_gridfile,
435
+ )
436
+ from .loadfuncs.write_files import _write_h5, write_file
437
+ from .toolfuncs.findlines import _check_var, find_contour, find_fieldlines
438
+ from .toolfuncs.fourier import fourier
439
+ from .toolfuncs.nabla import curl, divergence, gradient
440
+ from .toolfuncs.transform import (
441
+ _congrid,
442
+ cartesian_vector,
443
+ mirror,
444
+ reshape_cartesian,
445
+ reshape_uniform,
446
+ slices,
447
+ )
@@ -0,0 +1,71 @@
1
+ """Docstring for pyPLUTO.loadfuncs.baseloadtools module."""
2
+
3
+ import numpy as np
4
+
5
+ from pyPLUTO.baseloadmixin import BaseLoadMixin
6
+ from pyPLUTO.baseloadstate import BaseLoadState
7
+
8
+
9
+ class BaseLoadTools(BaseLoadMixin[BaseLoadState]):
10
+ """Docstring for BaseLoadTools class."""
11
+
12
+ def __init__(self, state: BaseLoadState) -> None:
13
+ """Initialize the BaseLoadTools class."""
14
+ self.state = state
15
+
16
+ def check_nout(self, nout: int | str | list[int | str]) -> None:
17
+ """Find the number of datafile to be loaded.
18
+
19
+ If nout is a list, the function checks if the list contains the keyword
20
+ 'last' or -1. If so, the keyword is replaced with the last file number.
21
+ If nout is a string, the function checks if the string contains the
22
+ keyword 'last' or -1. If so, the keyword is replaced with the last file
23
+ number. If nout is an integer, the function returns a list
24
+ containing the integer. If nout is 'all', the function returns a
25
+ list containing all the file numbers.
26
+
27
+ Returns
28
+ -------
29
+ - None
30
+
31
+ Parameters
32
+ ----------
33
+ - nout (not optional): int | str | list[int|str]
34
+ The output file to be loaded.
35
+ ----
36
+
37
+ Examples
38
+ --------
39
+ - Example #1: Load the last file
40
+ >>> _check_nout("last")
41
+ - Example #2: Load the first file
42
+ >>> _check_nout(0)
43
+ - Example #3: Load all the files
44
+ >>> _check_nout("all")
45
+ - Example #4: Load multiple specific files
46
+ >>> _check_nout([0, 1, 2, 3])
47
+ """
48
+ # Assign the last possible output file
49
+ last = self.outlist.tolist()[-1]
50
+
51
+ # Check if nout is a list and change the keywords
52
+ if not isinstance(nout, list):
53
+ # If nout is a string, get the keywords
54
+ Dnout = {nout: nout, "last": last, -1: last, "all": self.outlist}[
55
+ nout
56
+ ]
57
+ else:
58
+ # If nout is a list, replace the keywords
59
+ Dnout = [last if i in {"last", -1} else i for i in nout]
60
+
61
+ # Sort the list, compute the corresponding time and store its length
62
+ self.noutlist = np.sort(np.unique(np.atleast_1d(Dnout)))
63
+
64
+ # Check if the output files are in the list
65
+ if np.any(~np.isin(self.noutlist, self.outlist)):
66
+ raise ValueError(
67
+ f"Error: Wrong output file(s) {self.noutlist} \
68
+ in path {self.pathdir}."
69
+ )
70
+
71
+ # End of the function
@@ -0,0 +1,48 @@
1
+ """Module for code selection functionality."""
2
+
3
+ from typing import Any
4
+
5
+ from pyPLUTO.baseloadmixin import BaseLoadMixin
6
+ from pyPLUTO.baseloadstate import BaseLoadState
7
+ from pyPLUTO.codes.echo_load import EchoLoadManager
8
+ from pyPLUTO.loadstate import LoadState
9
+ from pyPLUTO.utils.inspector import track_kwargs
10
+
11
+
12
+ class CodeManager(BaseLoadMixin[BaseLoadState]):
13
+ """Class that manages the code selection."""
14
+
15
+ @track_kwargs
16
+ def __init__(
17
+ self,
18
+ state: BaseLoadState,
19
+ nout: int | str | list[int | str] | None,
20
+ **kwargs: Any,
21
+ ) -> None:
22
+ """Initialize the CodeManager class."""
23
+ self.state = state
24
+ if isinstance(state, LoadState):
25
+ self.echomanager = EchoLoadManager(state)
26
+
27
+ self.select_code(nout, **kwargs)
28
+
29
+ def select_code(
30
+ self, nout: int | str | list[int | str] | None, **kwargs: Any
31
+ ) -> None:
32
+ """Select the code based on the state."""
33
+ # If not code is provided (or the code is PLUTO/gPLUTO) just skip
34
+
35
+ codedict = {
36
+ "echo": self.echomanager.load_echo,
37
+ }
38
+
39
+ # If not code is provided (or the code is PLUTO/gPLUTO) just skip
40
+ if self.code.lower() in codedict:
41
+ if self.text is not False:
42
+ print(f"Loading data from code: {self.code}")
43
+ codedict[self.code.lower()](nout, **kwargs)
44
+
45
+ else:
46
+ raise NotImplementedError(
47
+ f"{self.code} loading is not implemented!"
48
+ )