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,277 @@
1
+ import glob
2
+ from pathlib import Path
3
+
4
+
5
+ def _check_pathformat(self, path: str | Path) -> None:
6
+ """Check if the path is consistent, i.e. if the path is given
7
+ through a non- empty string. If the path is consistent, it is
8
+ converted to a Path object. Then, a check is performed to see if the
9
+ path is a directory. The path is stored in the class as a Path
10
+ object self.pathdir.
11
+
12
+ Returns
13
+ -------
14
+ - None
15
+
16
+ Parameters
17
+ ----------
18
+ - path (not optional): str | Path
19
+ The path to the simulation directory.
20
+
21
+ ----
22
+
23
+ Examples
24
+ --------
25
+ - Example #1: path is a string
26
+
27
+ >>> _check_pathformat("path/to/simulation")
28
+
29
+ - Example #2: path is not a string
30
+
31
+ >>> _check_pathformat(1)
32
+ TypeError: Invalid data type. 'path' must be a non-empty string.
33
+
34
+ - Example #3: path is an empty string
35
+
36
+ >>> _check_pathformat("")
37
+ ValueError: 'path' cannot be an empty string.
38
+
39
+ - Example #4: path is not a directory
40
+
41
+ >>> _check_pathformat("path/to/simulation")
42
+ NotADirectoryError: Directory path/to/simulation not found.
43
+
44
+ """
45
+ # Check if the path is a non-empty string.
46
+ if not isinstance(path, str) and not isinstance(path, Path):
47
+ error = TypeError("Invalid data type. 'path' must be path or string")
48
+ raise TypeError(error)
49
+ # Check if the path is not empty
50
+ elif not isinstance(path, Path) and not path.strip():
51
+ raise ValueError("'path' cannot be an empty string.")
52
+ # Convert the path to a Path object and store it
53
+ else:
54
+ self.pathdir = Path(path)
55
+
56
+ # Check that the path is a directory
57
+ if not self.pathdir.is_dir():
58
+ raise NotADirectoryError(f"Directory {self.pathdir} not found.")
59
+
60
+ # End of the function
61
+
62
+
63
+ def _find_format(self, datatype: str | None, alone: bool | None) -> None:
64
+ """Finds the format of the data files to load. At first, the code
65
+ checks the filetype to be loaded (if fluid or particles). Then,
66
+ depending on the filetype given, the code checks if the
67
+ corresponding filetype is present Depending on the properties of the
68
+ filetype and of the type of the output (if fluid or particles)
69
+ different checks are performed. If no format is given or if the
70
+ given format is not found, the code checks the presence other
71
+ filetypes in the directory. If no file is found, an error is raised.
72
+ CUrrent filetypes available are dbl, flt, vtk, dbl.h5 and flt.h5.
73
+
74
+ Returns
75
+ -------
76
+ - None
77
+
78
+ Parameters
79
+ ----------
80
+ - alone (not optional): bool | None, default False
81
+ If the output files are standalone or they require a .out
82
+ file to be loaded. Only suggested for fluid files, .vtk
83
+ format and standalone files, otherwise the code finds
84
+ the alone property by itself.
85
+ - datatype (not optional): str | None, default None
86
+ The file format. If None the format is recovered between
87
+ (in order) dbl, flt, vtk, dbl.h5 and flt.h5.
88
+ Formats hdf5 (AMR) and tab have not been implemented yet.
89
+
90
+ ----
91
+
92
+ Examples
93
+ --------
94
+ - Example #1: Find the format of the fluid files
95
+
96
+ >>> _find_format("dbl", False)
97
+
98
+ - Example #2: Find the format of the standalone files
99
+
100
+ >>> _find_format("vtk", True)
101
+
102
+ - Example #3: Find the format of the fluid files (no format given)
103
+
104
+ >>> _find_format(None, False)
105
+
106
+ - Example #4: Find the format of the particles files
107
+
108
+ >>> _find_format("dbl", True)
109
+
110
+ """
111
+ # Initialization or declaration of variables
112
+ class_name = self.__class__.__name__ # The class name
113
+ dbl = {"dbl", "dbl.h5"} # The set of double filetypes
114
+
115
+ # Define the possible filetypes and set the keyword "alone" accordingly
116
+ if class_name == "Load":
117
+ # Divide the formats between standalone and not standalone
118
+ type_out = ["dbl", "flt", "vtk", "dbl.h5", "flt.h5", "tab"]
119
+ type_lon = ["vtk", "dbl.h5", "flt.h5", "tab", "hdf5"]
120
+ # If datatype is dbl or flt the files are not standalone
121
+ if datatype in {"dbl", "flt"}:
122
+ alone = False
123
+ elif class_name == "LoadPart":
124
+ # Particle files are always standalone
125
+ alone = True
126
+ type_out = []
127
+ type_lon = ["dbl", "flt", "vtk"]
128
+ else:
129
+ # If the class name is not recognized, raise an error
130
+ raise NameError("Invalid class name.")
131
+
132
+ # Check if the given datatype is valid, if not raise an error
133
+ if datatype not in type_out + type_lon + [None]:
134
+ if class_name == "Load":
135
+ err = (
136
+ f"Invalid datatype {datatype}.\n"
137
+ f"Possible formats are: dbl, flt, vtk, dbl.h5, flt.h5, tab"
138
+ )
139
+ elif class_name == "LoadPart":
140
+ err = (
141
+ f"Invalid datatype {datatype}.\n"
142
+ f"Possible formats are: dbl, flt, vtk"
143
+ )
144
+ raise ValueError(err)
145
+
146
+ # Create the list of types to iterate over. If the datatype is None
147
+ # then the list is the full list of types, otherwise the list is the
148
+ # datatype itself.
149
+ typeout0, typelon0 = (
150
+ ([], []) if datatype is not None else (type_out, type_lon)
151
+ )
152
+ type_out = [datatype] if datatype in type_out else typeout0
153
+ type_lon = [datatype] if datatype in type_lon else typelon0
154
+
155
+ # Create the list of functions to be called (.out or alone)
156
+ funcf = [_check_typeout] if len(type_out) > 0 and alone is not True else []
157
+ funcf += (
158
+ [_check_typelon] if len(type_lon) > 0 and alone is not False else []
159
+ )
160
+
161
+ # Define the dictionary for the function argument
162
+ dict_func = {"_check_typeout": type_out, "_check_typelon": type_lon}
163
+
164
+ # Iterate over the functions to be called
165
+ for do_check in funcf:
166
+ do_check(self, dict_func[do_check.__name__])
167
+
168
+ # Check if the format has been found
169
+ if self.format is not None:
170
+ # Store the charsize depending on the format
171
+ self._charsize = 8 if self.format in dbl else 4
172
+
173
+ # If the format is found, end the function
174
+ return None
175
+
176
+ # No file has been found, so raise an error depending on the case.
177
+ # If the datatype is None, raise a general error, otherwise raise
178
+ # an error for the specific datatype.
179
+ scrh = f"No available type has been found in {self.pathdir}."
180
+
181
+ if datatype is not None:
182
+ scrh = f"Type {datatype} not found."
183
+ raise FileNotFoundError(scrh)
184
+
185
+ # End of the function (never goes here, just for clarity)
186
+ return None
187
+
188
+
189
+ def _check_typeout(self, type_out: list[str]) -> None:
190
+ """Loops over possible formats in order to find, at first the
191
+ grid.out file, then the datatype.out file. If the datatype.out file
192
+ is found, the file format is selected and the flag alone is set to
193
+ False.
194
+
195
+ Returns
196
+ -------
197
+ - None
198
+
199
+ Parameters
200
+ ----------
201
+ - type_out (not optional): list[str]
202
+ The list of possible formats for the output file.
203
+
204
+ ----
205
+
206
+ Examples
207
+ --------
208
+ - Example #1: Check the format of the output files
209
+
210
+ >>> _check_typeout(["dbl", "flt", "vtk", "dbl.h5", "flt.h5", "tab"])
211
+
212
+ - Example #2: Check the format of the output files (no format given)
213
+
214
+ >>> _check_typeout([])
215
+
216
+ """
217
+ # Loop over the possible formats
218
+ for try_type in type_out:
219
+ # Create the path to the grid.out and datatype.out files
220
+ self._pathgrid = self.pathdir / "grid.out"
221
+ self._pathdata = self.pathdir / (try_type + ".out")
222
+
223
+ # Check if the datatype.out file is present
224
+ if self._pathdata.is_file() and self._pathgrid.is_file():
225
+ # Store the format and set the flag alone to False
226
+ self.format = try_type
227
+ self._alone = False
228
+ # Format is found, break the loop
229
+ break
230
+
231
+ # End of the function
232
+
233
+
234
+ def _check_typelon(self, type_lon: list[str]) -> None:
235
+ """Loops over posisble formats in order to find matching files with
236
+ the datatype. If the file is found, the file format is selected and
237
+ the flag alone is set to True.
238
+
239
+ Returns
240
+ -------
241
+ - None
242
+
243
+ Parameters
244
+ ----------
245
+ - type_lon (not optional): list[str]
246
+ The list of possible formats for the output file.
247
+
248
+ ----
249
+
250
+ Examples
251
+ --------
252
+ - Example #1: Check the format of the output files
253
+
254
+ >>> _check_typelon(["dbl", "flt", "vtk"])
255
+
256
+ - Example #2: Check the format of the output files (no format given)
257
+
258
+ >>> _check_typelon([])
259
+
260
+ """
261
+ # Loop over the possible formats
262
+ for try_type in type_lon:
263
+ # Create the pattern to be searched
264
+ pattern: Path = self.pathdir / ("*.*." + try_type)
265
+
266
+ # Find the files matching the pattern
267
+ self._matching_files = glob.glob(str(pattern))
268
+
269
+ # Check if the file is present
270
+ if self._matching_files:
271
+ # Store the format and set the flag alone to True
272
+ self.format = try_type
273
+ self._alone = True
274
+ # Format is found, break the loop
275
+ break
276
+
277
+ # End of the functionv
@@ -0,0 +1,224 @@
1
+ """Module for grid management when reading files without descriptor."""
2
+
3
+ import warnings
4
+
5
+ import numpy as np
6
+
7
+ from ..loadmixin import LoadMixin
8
+ from ..loadstate import LoadState
9
+
10
+
11
+ class GridManager(LoadMixin):
12
+ """Docstring for BaseLoadTools class."""
13
+
14
+ def __init__(self, state: LoadState) -> None:
15
+ """Initialize the BaseLoadTools class."""
16
+ self.state: LoadState = state
17
+
18
+ def readgridvtk(self, gridvars: list[str]) -> None:
19
+ """Read the grid from a .vtk file.
20
+
21
+ Returns
22
+ -------
23
+ - None
24
+
25
+ Parameters
26
+ ----------
27
+ - gridvars (not optional): list[str]
28
+ The list of grid variables.
29
+
30
+ ----
31
+
32
+ Examples
33
+ --------
34
+ - Example #1: Read the grid from a vtk file
35
+
36
+ >>> _read_grid_vtk(["self.x1r", "self.x2r", "self.x3r"])
37
+
38
+ """
39
+ # - RECTILINEAR GRID
40
+ # Variables that we already have: x1r x2r x3r nshp dim nx1 nx2 nx3
41
+ # Variables that we need: x1 x2 x3 dx1 dx2 dx3 gridsize
42
+
43
+ self.gridsize = self.nx1 * self.nx2 * self.nx3
44
+ twod = 2
45
+
46
+ if self.geom == "UNKNOWN":
47
+ if gridvars[0] == "x1r":
48
+ self.x1 = 0.5 * (self.x1r[1:] + self.x1r[:-1])
49
+ self.x1 = (
50
+ 0.5 * (self.x1[:, 1:] + self.x1[:, :-1])
51
+ if self.dim > 1
52
+ else self.x1
53
+ )
54
+ self.x1 = (
55
+ 0.5 * (self.x1[:, :, 1:] + self.x1[:, :, :-1])
56
+ if self.dim > twod
57
+ else self.x1
58
+ )
59
+
60
+ """
61
+ self.dx1 = self.x1r[1:] - self.x1r[:-1]
62
+ self.dx1 = (
63
+ 0.5 * (self.dx1[:, 1:] + self.dx1[:, :-1])
64
+ if self.dim > 1
65
+ else self.dx1
66
+ )
67
+ self.dx1 = (
68
+ 0.5 * (self.dx1[:, :, 1:] + self.dx1[:, :, :-1])
69
+ if self.dim > twod
70
+ else self.dx1
71
+ )
72
+ """
73
+
74
+ if gridvars[1] == "x2r":
75
+ self.x2 = 0.5 * (self.x2r[1:] + self.x2r[:-1])
76
+ self.x2 = 0.5 * (self.x2[:, 1:] + self.x2[:, :-1])
77
+ self.x2 = (
78
+ 0.5 * (self.x2[:, :, 1:] + self.x2[:, :, :-1])
79
+ if self.dim > twod
80
+ else self.x2
81
+ )
82
+
83
+ """
84
+ self.dx2 = self.x2r[1:] - self.x2r[:-1]
85
+ self.dx2 = 0.5 * (self.dx2[:, 1:] + self.dx2[:, :-1])
86
+ self.dx2 = (
87
+ 0.5 * (self.dx2[:, :, 1:] + self.dx2[:, :, :-1])
88
+ if self.dim > twod
89
+ else self.dx2
90
+ )
91
+ """
92
+
93
+ if gridvars[2] == "x3r":
94
+ self.x3 = 0.5 * (self.x3r[1:] + self.x3r[:-1])
95
+ self.x3 = 0.5 * (self.x3[:, 1:] + self.x3[:, :-1])
96
+ self.x3 = 0.5 * (self.x3[:, :, 1:] + self.x3[:, :, :-1])
97
+
98
+ """
99
+ self.dx3 = self.x3r[1:] - self.x3r[:-1]
100
+ self.dx3 = 0.5*(self.dx3[:, 1:] + self.dx3[:, :-1])
101
+ self.dx3 = 0.5*(self.dx3[:, :, 1:] + self.dx3[:, :, :-1])
102
+ """
103
+
104
+ warn = (
105
+ "The geometry is unknown, therefore the grid spacing has not "
106
+ "been computed. \nFor a more accurate grid analysis, the "
107
+ "loading with the .out file is recommended.\n"
108
+ )
109
+ warnings.warn(warn, UserWarning, stacklevel=2)
110
+
111
+ return None
112
+
113
+ if gridvars[0] == "x1r":
114
+ self.x1 = 0.5 * (self.x1r[:-1] + self.x1r[1:])
115
+ self.dx1 = self.x1r[1:] - self.x1r[:-1]
116
+ if gridvars[1] == "x2r":
117
+ self.x2 = 0.5 * (self.x2r[:-1] + self.x2r[1:])
118
+ self.dx2 = self.x2r[1:] - self.x2r[:-1]
119
+ if gridvars[2] == "x3r":
120
+ self.x3 = 0.5 * (self.x3r[:-1] + self.x3r[1:])
121
+ self.dx3 = self.x3r[1:] - self.x3r[:-1]
122
+
123
+ return None
124
+
125
+ def readgridh5(self) -> None:
126
+ """Read the grid from a .h5 file.
127
+
128
+ Returns
129
+ -------
130
+ - None
131
+
132
+ Parameters
133
+ ----------
134
+ - None
135
+
136
+ ----
137
+
138
+ Examples
139
+ --------
140
+ - Example #1: Read the grid from a .h5 file
141
+
142
+ >>> _read_grid_h5()
143
+
144
+ """
145
+ # Variables that we already have: x1 x2 x3 x1r x2r x3r
146
+ # Variables that we need: nx1 nx2 nx3 nshp nx1s nx2s nx3s dim
147
+ # nshp_st1 nshp_st2 nshp_st3
148
+ # gridsize gridsize_st1 gridsize_st2 gridsize_st3
149
+ nshp = np.shape(self.x1)
150
+ if isinstance(nshp, int):
151
+ nshp = (nshp,)
152
+
153
+ self.nshp = nshp
154
+ self.dim = len(nshp)
155
+ self.geom = "UNKNOWN"
156
+ self.nx1, self.nx2, self.nx3 = ((*nshp, 1, 1, 1))[:3]
157
+ nx1s, nx2s, nx3s = self.nx1 + 1, self.nx2 + 1, self.nx3 + 1
158
+
159
+ GRID_SHAPES = {
160
+ 1: lambda nx1, _, __: (nx1s, None, None),
161
+ 2: lambda nx1, nx2, _: ((nx2, nx1s), (nx2s, nx1), None),
162
+ 3: lambda nx1, nx2, nx3: (
163
+ (nx3, nx2, nx1s),
164
+ (nx3, nx2s, nx1),
165
+ (nx3s, nx2, nx1),
166
+ ),
167
+ }
168
+
169
+ # Determine grid shape based on dimension
170
+ (self.nshp_st1, self.nshp_st2, self.nshp_st3) = GRID_SHAPES[self.dim](
171
+ self.nx1, self.nx2, self.nx3
172
+ )
173
+
174
+ # Grid spacing has been temporarily removed from the .h5 file
175
+ """
176
+ self.dx1 = self.x1r[1:] - self.x1r[:-1]
177
+ self.dx1 = (
178
+ 0.5 * (self.dx1[:, 1:] + self.dx1[:, :-1])
179
+ if self.dim > 1
180
+ else self.dx1
181
+ )
182
+ self.dx1 = (
183
+ 0.5 * (self.dx1[:, :, 1:] + self.dx1[:, :, :-1])
184
+ if self.dim > 2
185
+ else self.dx1
186
+ )
187
+
188
+ self.dx2 = self.x2r[1:] - self.x2r[:-1]
189
+ self.dx2 = (
190
+ 0.5 * (self.dx2[:, 1:] + self.dx2[:, :-1])
191
+ if self.dim > 1
192
+ else self.dx2
193
+ )
194
+ self.dx2 = (
195
+ 0.5 * (self.dx2[:, :, 1:] + self.dx2[:, :, :-1])
196
+ if self.dim > 2
197
+ else self.dx2
198
+ )
199
+
200
+ self.dx3 = self.x3r[1:] - self.x3r[:-1]
201
+ self.dx3 = (
202
+ 0.5 * (self.dx3[:, 1:] + self.dx3[:, :-1])
203
+ if self.dim > 1
204
+ else self.dx3
205
+ )
206
+ self.dx3 = (
207
+ 0.5 * (self.dx3[:, :, 1:] + self.dx3[:, :, :-1])
208
+ if self.dim > 2
209
+ else self.dx3
210
+ )
211
+ """
212
+
213
+ # Compute the gridsize both centered and staggered
214
+ self.gridsize = self.nx1 * self.nx2 * self.nx3
215
+ self.gridsize_st1 = nx1s * self.nx2 * self.nx3
216
+ self.gridsize_st2 = self.nx1 * nx2s * self.nx3
217
+ self.gridsize_st3 = self.nx1 * self.nx2 * nx3s
218
+
219
+ warn = (
220
+ "The geometry is unknown, therefore the grid spacing has not been "
221
+ "computed. \nFor a more accurate grid analysis, the loading with "
222
+ "the .out file is recommended.\n"
223
+ )
224
+ warnings.warn(warn, UserWarning, stacklevel=2)