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,408 @@
1
+ """Docstring for pyPLUTO.loadfuncs.offsetfluid module."""
2
+
3
+ import mmap
4
+ import struct
5
+ import warnings
6
+ from pathlib import Path
7
+
8
+ import h5py
9
+ import numpy as np
10
+
11
+ from pyPLUTO.loadfuncs.readgridalone import GridManager
12
+ from pyPLUTO.loadmixin import LoadMixin
13
+ from pyPLUTO.loadstate import LoadState
14
+
15
+
16
+ class OffsetFluid(LoadMixin):
17
+ """Class that computes the fluid offsets in single_file format."""
18
+
19
+ from pyPLUTO.amr import _DataScanHDF5, _inspect_hdf5, _read_gridfile
20
+ from pyPLUTO.loadfuncs.readgridout import _split_gridfile
21
+ from pyPLUTO.toolfuncs.transform import _congrid
22
+
23
+ def __init__(self, state: LoadState) -> None:
24
+ self.state = state
25
+ self.varoffset, self.varshape = ({}, {})
26
+ self.GridAloneManager = GridManager(state)
27
+
28
+ def offset_bin(
29
+ self, _i: int, var: str | None, exout: int, _mm: mmap.mmap
30
+ ) -> None:
31
+ """Compute the offset and shape of the variables to be loaded.
32
+
33
+ The routine, knowing the grid shape, computes the offset and stores the
34
+ shape dependng on wether the variable is staggered or not.
35
+
36
+ Returns
37
+ -------
38
+ - None
39
+
40
+ Parameters
41
+ ----------
42
+ - i (not optional): int
43
+ The index of the file to be loaded.
44
+ - var (not optional): str
45
+ The variable to be loaded.
46
+
47
+ ----
48
+
49
+ Examples
50
+ --------
51
+ - Example #1: Load all the variables
52
+
53
+ >>> _offset_bin(0, True)
54
+
55
+ """
56
+ off_start = 0
57
+
58
+ grid_sizes: dict[str, tuple[int | tuple[int, ...] | None, int]] = {
59
+ "Bx1s": (self.nshp_st1, self.gridsize_st1),
60
+ "Ex1s": (self.nshp_st1, self.gridsize_st1),
61
+ "Bx2s": (self.nshp_st2, self.gridsize_st2),
62
+ "Ex2s": (self.nshp_st2, self.gridsize_st2),
63
+ "Bx3s": (self.nshp_st3, self.gridsize_st3),
64
+ "Ex3s": (self.nshp_st3, self.gridsize_st3),
65
+ }
66
+
67
+ # Loop over the variables to be loaded (None for single files)
68
+ varloop = self.d_info["varslist"][exout] if var is None else [var]
69
+
70
+ for eachvar in varloop:
71
+ # Get the grid shape and size (centered or staggered)
72
+ grid_size = grid_sizes.get(eachvar, [self.nshp, self.gridsize])
73
+ self.varshape[eachvar] = grid_size[0]
74
+ # Assign the offset
75
+ self.varoffset[eachvar] = off_start
76
+ # Move to next variable
77
+ if isinstance(grid_size[1], int):
78
+ off_start += grid_size[1] * self.charsize
79
+ else:
80
+ raise ValueError("Grid size must be an integer.")
81
+
82
+ # End of function
83
+
84
+ def offset_h5(
85
+ self, i: int, _var: str | None, exout: int, _mm: mmap.mmap
86
+ ) -> None:
87
+ """Compute the offset and shape of the variable in hdf5 format.
88
+
89
+ The routine, knowing the grid shape, computes the offset and stores the
90
+ shape dependng on wether the variable is staggered or not.
91
+
92
+ Returns
93
+ -------
94
+ - None
95
+
96
+ Parameters
97
+ ----------
98
+ - i (not optional): int
99
+ The index of the file to be loaded.
100
+ - var (not optional): str
101
+ The variable to be loaded.
102
+
103
+ ----
104
+
105
+ Examples
106
+ --------
107
+ - Example #1: Load all the variables
108
+
109
+ >>> _offset_h5(0, True)
110
+
111
+ """
112
+ # Open the file with the h5py library
113
+ h5file = h5py.File(str(self.filepath), "r")
114
+
115
+ # Selects the binformat
116
+ self.d_info["binformat"][exout] = (
117
+ "d" if self.format == "dbl.h5" else "f"
118
+ )
119
+
120
+ # Safely access the timestep group and its sub-items to avoid
121
+ # treating an h5py.Datatype as a subscriptable object.
122
+ timestep_key = f"Timestep_{exout}"
123
+ timestep = h5file.get(timestep_key, None)
124
+
125
+ if isinstance(timestep, h5py.Group):
126
+ timeattr = timestep.attrs["Time"]
127
+ idx = np.searchsorted(self.outlist, exout)
128
+ self.timelist[idx] = float(timeattr)
129
+ idx = np.searchsorted(self.noutlist, exout)
130
+ self.ntimelist[idx] = float(timeattr)
131
+ cellvs = timestep.get("vars", {})
132
+ stagvs = timestep.get("stag_vars", {})
133
+ cellvs = (
134
+ {}
135
+ if cellvs is None or isinstance(cellvs, h5py.Datatype)
136
+ else cellvs
137
+ )
138
+
139
+ stagvs = (
140
+ {}
141
+ if stagvs is None or isinstance(stagvs, h5py.Datatype)
142
+ else stagvs
143
+ )
144
+ else:
145
+ # Timestep group not present or not a group; treat as empty
146
+ cellvs = {}
147
+ stagvs = {}
148
+
149
+ # If standalone file, finds the variables to be loaded, else
150
+ # remove variables in the .out file that are not present in the actual
151
+ # file
152
+ if (
153
+ self.alone is True
154
+ and isinstance(cellvs, h5py.Group | dict)
155
+ and isinstance(stagvs, h5py.Group | dict)
156
+ ):
157
+ self.d_info["varslist"][exout] = set(cellvs.keys()) | set(
158
+ stagvs.keys()
159
+ )
160
+ elif not isinstance(cellvs, h5py.Group | dict) or not isinstance(
161
+ stagvs, h5py.Group | dict
162
+ ):
163
+ raise ValueError(
164
+ "Error: Variables group not found in the HDF5 file."
165
+ )
166
+
167
+ # Loop over the variables and store the offset and shape
168
+ for j in self.d_info["varslist"][exout]:
169
+ if j in cellvs:
170
+ obj = cellvs[j]
171
+ elif j in stagvs:
172
+ obj = stagvs[j]
173
+ else:
174
+ obj = None
175
+ warnings.warn(
176
+ f"Warning: Variable {j} not found in the HDF5 file.",
177
+ UserWarning,
178
+ stacklevel=2,
179
+ )
180
+ # Only Dataset objects provide shape and a file offset
181
+ if isinstance(obj, h5py.Dataset):
182
+ self.varoffset[j] = obj.id.get_offset()
183
+ self.varshape[j] = obj.shape
184
+ elif obj is not None:
185
+ raise ValueError(
186
+ f"Error: Variable {j} in the HDF5 file is not a dataset."
187
+ )
188
+
189
+ if self.alone is True and self.infogrid is True:
190
+ self.x1 = h5file["cell_coords"]["X"][:].T
191
+ self.x2 = h5file["cell_coords"]["Y"][:].T
192
+ self.x3 = h5file["cell_coords"]["Z"][:].T
193
+ self.x1r = h5file["node_coords"]["X"][:].T
194
+ self.x2r = h5file["node_coords"]["Y"][:].T
195
+ self.x3r = h5file["node_coords"]["Z"][:].T
196
+ self.GridAloneManager.readgridh5()
197
+ self.infogrid = False
198
+
199
+ # Close the file
200
+ h5file.close()
201
+
202
+ def offset_vtk(
203
+ self, i: int, var: str | None, exout: int, mm: mmap.mmap
204
+ ) -> None:
205
+ """Compute the offset and shape of the variables to be loaded.
206
+
207
+ The routine, knowing the grid shape, computes the offset and stores the
208
+ shape dependng on wether the variable is staggered or not.
209
+
210
+ Returns
211
+ -------
212
+ - None
213
+
214
+ Parameters
215
+ ----------
216
+ - i (not optional): int
217
+ The index of the file to be loaded.
218
+ - var (not optional): str
219
+ The variable to be loaded.
220
+
221
+ ----
222
+
223
+ Examples
224
+ --------
225
+ - Example #1: Load all the variables
226
+
227
+ >>> _offset_vtk(0, True)
228
+
229
+ """
230
+ dir_map: dict[str, str] = {}
231
+ gridvars: list[str] = []
232
+
233
+ self.d_info["endianess"][exout] = (
234
+ ">" if self.endian is None else self.d_info["endianess"][exout]
235
+ )
236
+ if self.d_info["endianess"][exout] is None:
237
+ raise ValueError("Error: Wrong endianess in vtk file.")
238
+
239
+ if self.alone is True:
240
+ self.d_info["binformat"][exout] = (
241
+ f"{self.d_info['endianess'][exout]}f{self.charsize}"
242
+ )
243
+ search_pos = 0
244
+ while True:
245
+ line_end = mm.find(b"\n", search_pos)
246
+ if line_end == -1:
247
+ break # No more occurrences found
248
+ line = mm[search_pos:line_end]
249
+
250
+ if line.startswith(b"SCALARS"):
251
+ parts = line.split()
252
+ namevar = parts[1].decode()
253
+
254
+ # Move to the start of the scalar data
255
+ lookup_table_pos = mm.find(b"LOOKUP_TABLE default", line_end)
256
+ offset = mm.find(b"\n", lookup_table_pos) + 1
257
+
258
+ self.varoffset[namevar] = offset
259
+ self.varshape[namevar] = self.nshp
260
+ if var is not None:
261
+ break
262
+
263
+ search_pos = offset + self.gridsize * self.charsize
264
+
265
+ elif line.startswith(b"VECTORS"):
266
+ # Handle VECTORS data
267
+ warnings.warn(
268
+ "Warning: VECTORS data is not supported.",
269
+ UserWarning,
270
+ stacklevel=2,
271
+ )
272
+ search_pos = line_end + 1
273
+ elif line.startswith(b"DIMENSIONS") and self.infogrid is True:
274
+ self.nx1, self.nx2, self.nx3 = [
275
+ max(int(i) - 1, 1) for i in line.split()[1:4]
276
+ ]
277
+ if self.nx3 == 1 and self.nx2 == 1:
278
+ self.dim = 1
279
+ self.nshp = self.nx1
280
+ self.gridsize = self.nx1
281
+ nshp_grid = self.nx1 + 1
282
+ gridvars = ["x1r", "x2", "x3"]
283
+ elif self.nx3 == 1:
284
+ self.dim = 2
285
+ self.nshp = (self.nx2, self.nx1)
286
+ self.gridsize = self.nx1 * self.nx2
287
+ nshp_grid = (self.nx2 + 1, self.nx1 + 1)
288
+ gridvars = ["x1r", "x2r", "x3"]
289
+ else:
290
+ self.dim = 3
291
+ self.nshp = (self.nx3, self.nx2, self.nx1)
292
+ self.gridsize = self.nx1 * self.nx2 * self.nx3
293
+ nshp_grid = (self.nx3 + 1, self.nx2 + 1, self.nx1 + 1)
294
+ gridvars = ["x1r", "x2r", "x3r"]
295
+ dir_map = {"X": gridvars[0], "Y": gridvars[1], "Z": gridvars[2]}
296
+ search_pos = line_end + 1
297
+ elif line.startswith(b"TIME") and self.alone is True:
298
+ try:
299
+ parts = line.split()
300
+ binf = 8 if parts[3].decode() == "double" else 4
301
+ raw = mm[line_end + 1 : line_end + 1 + binf]
302
+ scrh = struct.unpack(
303
+ self.d_info["endianess"][exout] + "d", raw
304
+ )[0]
305
+ self.timelist[exout] = scrh
306
+ idx = np.searchsorted(self.noutlist, exout)
307
+ self.ntimelist[idx] = scrh
308
+ except Exception:
309
+ binf = 0
310
+ search_pos = line_end + 1 + binf
311
+
312
+ elif line[1:].startswith(b"_COORDINATES") and self.infogrid is True:
313
+ self.geom = "CARTESIAN"
314
+ linesplit = line.split()
315
+ var_sel = linesplit[0].decode()[0]
316
+ binf = (
317
+ self.d_info["endianess"][exout] + "d"
318
+ if linesplit[2].decode() == "double"
319
+ else self.d_info["endianess"][exout] + "f"
320
+ )
321
+ scrh = np.ndarray(
322
+ shape=int(linesplit[1]),
323
+ dtype=binf,
324
+ buffer=mm,
325
+ offset=line_end + 1,
326
+ order="C",
327
+ ).T
328
+ setattr(self, dir_map[var_sel], scrh)
329
+ search_pos = line_end + 1
330
+ else:
331
+ search_pos = line_end + 1
332
+
333
+ if (
334
+ self.d_info["typefile"][exout] == "single_file"
335
+ and self.alone is True
336
+ ):
337
+ self.d_info["varslist"][exout] = list(self.varoffset.keys())
338
+ if self.infogrid is True:
339
+ self.GridAloneManager.readgridvtk(gridvars)
340
+ self.infogrid = False
341
+
342
+ def offset_hdf5(
343
+ self, i: int, _var: str | None, exout: int, _mm: mmap.mmap
344
+ ) -> None:
345
+ """Load AMR data from PLUTO/Chombo HDF5 files.
346
+
347
+ This method is intentionally isolated from other formats.
348
+ """
349
+ # Bridge AMR helpers (legacy naming) to the Newload state fields.
350
+ self._filepath = self.filepath
351
+ self._pathgrid = self.pathdir / Path("grid.out")
352
+ if not hasattr(self, "level"):
353
+ self.level = 0
354
+
355
+ # Keep the original varslist structure used by Newload internals.
356
+ varslist_table = self.d_info.get("varslist", None)
357
+ self._inspect_hdf5(i, exout)
358
+
359
+ # AMR reader stores a flat variable list; normalize as plain strings.
360
+ loaded_vars = []
361
+ for v in self.d_info.get("varslist", []):
362
+ loaded_vars.append(v.decode() if isinstance(v, bytes) else str(v))
363
+
364
+ if (
365
+ isinstance(varslist_table, list)
366
+ and len(varslist_table) > exout
367
+ and isinstance(varslist_table[exout], list | set | np.ndarray)
368
+ ):
369
+ self.d_info["varslist"] = varslist_table
370
+ self.d_info["varslist"][exout] = loaded_vars
371
+ else:
372
+ self.d_info["varslist"] = loaded_vars
373
+
374
+ self.load_vars = loaded_vars
375
+
376
+ # Persist AMR metadata to state so Newload exposes it.
377
+ for amr_key in ("AMRLevel", "AMRBoxes", "Dt", "n1", "n2", "n3"):
378
+ if hasattr(self, amr_key):
379
+ setattr(self.state, amr_key, getattr(self, amr_key))
380
+
381
+ # Keep times aligned with nout/out tables when available.
382
+ try:
383
+ idx = np.searchsorted(self.outlist, exout)
384
+ self.timelist[idx] = float(self.ntime)
385
+ except Exception:
386
+ pass
387
+ try:
388
+ idx = np.searchsorted(self.noutlist, exout)
389
+ self.ntimelist[idx] = float(self.ntime)
390
+ except Exception:
391
+ pass
392
+
393
+ # Populate d_vars so Newload can expose loaded AMR variables normally.
394
+ for varname in loaded_vars:
395
+ if not hasattr(self, varname):
396
+ continue
397
+ data = getattr(self, varname)
398
+ self.varshape[varname] = np.shape(data)
399
+ self.varoffset[varname] = 0
400
+
401
+ if self.lennout != 1:
402
+ if varname not in self.d_vars:
403
+ self.d_vars[varname] = {}
404
+ self.d_vars[varname][exout] = data
405
+ else:
406
+ self.d_vars[varname] = data
407
+
408
+ self.infogrid = False
@@ -0,0 +1,213 @@
1
+ import warnings
2
+ from typing import Any
3
+
4
+ import h5py
5
+ import numpy as np
6
+
7
+
8
+ def read_vtk(self) -> None:
9
+ """Read the data from a VTK file.
10
+
11
+ Returns
12
+ -------
13
+ - None
14
+
15
+ Parameters
16
+ ----------
17
+ - None
18
+
19
+ ----
20
+
21
+ Examples
22
+ --------
23
+ - Example #1: Read the data from a VTK file
24
+
25
+ >>> read_vtk()
26
+
27
+ """
28
+ raise NotImplementedError("read_vtk() is not yet implemented.")
29
+
30
+
31
+ def _read_h5(self, filename: str, **kwargs: Any) -> None:
32
+ """Read the data from a HDF5 file.
33
+
34
+ Returns
35
+ -------
36
+ - the data in a dictionary
37
+
38
+ Parameters
39
+ ----------
40
+ - filename: str
41
+ The name of the file to be read.
42
+ - kwargs: Any
43
+ Any additional arguments.
44
+
45
+ ----
46
+
47
+ Examples
48
+ --------
49
+ - Example #1: Read the data from a HDF5 file
50
+
51
+ >>> read_h5("filename.h5")
52
+
53
+ """
54
+ # Create the path to the HDF5 file
55
+ try:
56
+ self._pathh5 = self.pathdir / filename
57
+ except FileNotFoundError:
58
+ self._pathh5 = filename
59
+
60
+ # Open the HDF5 file
61
+ data_dict = {}
62
+ with h5py.File(self._pathh5, "r") as f:
63
+ for key in f.keys():
64
+ data_dict[key] = f[key][()] # Store data in the dictionary
65
+
66
+ return data_dict # Return the dictionary
67
+
68
+
69
+ def read_tab(self) -> None:
70
+ """Read the data from a tab file.
71
+
72
+ Returns
73
+ -------
74
+ - None
75
+
76
+ Parameters
77
+ ----------
78
+ - None
79
+
80
+ ----
81
+
82
+ Examples
83
+ --------
84
+ - Example #1: Read the data from a tab file
85
+
86
+ >>> read_tab()
87
+
88
+ """
89
+ raise NotImplementedError("read_tab() is not yet implemented.")
90
+
91
+
92
+ def read_bin(self) -> None:
93
+ """Read the data from a binary file.
94
+
95
+ Returns
96
+ -------
97
+ - None
98
+
99
+ Parameters
100
+ ----------
101
+ - None
102
+
103
+ ----
104
+
105
+ Examples
106
+ --------
107
+ - Example #1: Read the data from a binary file
108
+
109
+ >>> read_bin()
110
+
111
+ """
112
+ raise NotImplementedError("read_bin() is not yet implemented.")
113
+
114
+
115
+ def _read_dat(self, filename: str, **kwargs: Any) -> None:
116
+ """Read the data from a dat file.
117
+
118
+ Returns
119
+ -------
120
+ - The file columns as a dicionary
121
+
122
+ Parameters
123
+ ----------
124
+ - filename (not optional): str
125
+ The name of the file to be read.
126
+ - kwargs: Any
127
+ Any additional arguments.
128
+ - names: bool, default True
129
+ If True, checks for column names in the file.
130
+ - skip: int, default 0
131
+ The number of rows to skip.
132
+
133
+ ----
134
+
135
+ Examples
136
+ --------
137
+ - Example #1: Read the data from a dat file
138
+
139
+ >>> read_dat("filename.dat")
140
+
141
+ """
142
+ # Create the path to the HDF5 file
143
+ try:
144
+ self._pathh5 = self.pathdir / filename
145
+ except FileNotFoundError:
146
+ self._pathh5 = filename
147
+
148
+ names = kwargs.get("names", True)
149
+ skip = kwargs.get("skip", 0)
150
+
151
+ # Open the dat file with np.genfromtext
152
+ data = np.genfromtxt(self._pathh5, names=names, skip_header=skip)
153
+ if names:
154
+ loop = data.dtype.names
155
+ analysis = {name: data[name] for name in loop}
156
+ else:
157
+ loop = range(data.shape[1])
158
+ analysis = {f"col_{i}": data[:, i] for i in loop}
159
+
160
+ return analysis
161
+
162
+
163
+ def read_file(
164
+ self, filename: str, datatype: str | None = None, **kwargs: Any
165
+ ) -> Any:
166
+ """Read the data from the output files.
167
+
168
+ Returns
169
+ -------
170
+ - the data as a dicionary
171
+
172
+ Parameters
173
+ ----------
174
+ - filename (not optional): str
175
+ The name of the file to be read.
176
+ - datatype: str
177
+ The type of the file.
178
+ - **kwargs: Any
179
+ Any additional arguments.
180
+
181
+ ----
182
+
183
+ Examples
184
+ --------
185
+ - Example #1: Read the data from the output files
186
+
187
+ >>> read_files()
188
+
189
+ """
190
+ # Check the datatype of the input data
191
+ if datatype is None:
192
+ datatype = filename.rsplit(".", maxsplit=1)[-1]
193
+ poss_types = {"dbl", "flt", "vtk", "h5", "tab", "dat"}
194
+ if datatype not in poss_types:
195
+ warn = f"Invalid datatype: {datatype}. Resetting to 'h5'"
196
+ warnings.warn(warn)
197
+ datatype = "h5"
198
+
199
+ # Check the format of the output files
200
+ if datatype == "h5":
201
+ res = _read_h5(self, filename, **kwargs)
202
+ elif datatype == "dat":
203
+ res = _read_dat(self, filename, **kwargs)
204
+ else:
205
+ warn = (
206
+ f"Invalid datatype: {datatype}, not implemented yet! "
207
+ "Resetting to 'h5'"
208
+ )
209
+ warnings.warn(warn)
210
+ pass
211
+
212
+ # End of the function
213
+ return res