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,177 @@
1
+ from PySide6.QtWidgets import (
2
+ QHBoxLayout,
3
+ QMainWindow,
4
+ QTextEdit,
5
+ QVBoxLayout,
6
+ QWidget,
7
+ )
8
+
9
+ from .globals import cmaps_avail, cmaps_divided, format_avail, scales, vscales
10
+
11
+
12
+ class PyPLUTOApp(QMainWindow):
13
+ def __init__(self, code: str):
14
+ super().__init__()
15
+ codestr = f" ({self.code:= code})" if code != "PLUTO" else ""
16
+ self.setWindowTitle(f"PyPLUTO GUI{codestr}")
17
+ if code != "PLUTO":
18
+ raise NotImplementedError(f"Code {code} not yet implemented")
19
+
20
+ self.folder_path = None
21
+ self.datatype = None
22
+ self.data_loaded = False
23
+
24
+ main_widget = QWidget()
25
+ self.setCentralWidget(main_widget)
26
+ main_layout = QHBoxLayout(main_widget)
27
+
28
+ # Left control panel
29
+ button_layout = QVBoxLayout()
30
+
31
+ layout = QHBoxLayout()
32
+ self.add_combobox(
33
+ "datatype_selector",
34
+ layout,
35
+ ["PLUTO fluid", "PLUTO particles", "ECHO"],
36
+ )
37
+ self.add_label("Preferred format:", layout)
38
+ self.add_combobox("format_selector", layout, format_avail)
39
+ button_layout.addLayout(layout)
40
+
41
+ layout = QHBoxLayout()
42
+ self.add_label("nout:", layout)
43
+ self.add_lineedit("outtext", layout, "nout")
44
+ self.add_label("vars:", layout)
45
+ self.add_lineedit("varstext", layout, "vars")
46
+ button_layout.addLayout(layout)
47
+
48
+ layout = QHBoxLayout()
49
+ self.add_pushbutton("Select File", layout, self.select_folder)
50
+ self.add_pushbutton("Clear", layout, self.clearload)
51
+ self.add_pushbutton("Reload Folder", layout, self.reload_data)
52
+ button_layout.addLayout(layout)
53
+
54
+ self.add_line(button_layout)
55
+
56
+ layout = QHBoxLayout()
57
+ self.add_label("Select the variable to plot:", layout)
58
+ self.add_combobox("var_selector", layout, [])
59
+ self.add_checkbox("Transpose", layout, "transpose_checkbox")
60
+ button_layout.addLayout(layout)
61
+
62
+ layout = QHBoxLayout()
63
+ self.add_label("Select the x-axis:", layout)
64
+ self.add_combobox("xaxis_selector", layout, [], 100)
65
+ self.add_label("y-axis:", layout)
66
+ self.add_combobox("yaxis_selector", layout, [], 100)
67
+ button_layout.addLayout(layout)
68
+
69
+ layout = QHBoxLayout()
70
+ self.add_label("Slices: x", layout)
71
+ self.add_lineedit("xslicetext", layout, "x-slice")
72
+ self.add_label("y", layout)
73
+ self.add_lineedit("yslicetext", layout, "y-slice")
74
+ self.add_label("z", layout)
75
+ self.add_lineedit("zslicetext", layout, "z-slice")
76
+ button_layout.addLayout(layout)
77
+
78
+ self.add_line(button_layout)
79
+
80
+ layout = QHBoxLayout()
81
+ self.add_label("Insert Title:", layout)
82
+ self.add_lineedit("plot_title", layout, "title")
83
+ self.add_checkbox("Auto-ratio", layout, "ratio_checkbox")
84
+ self.ratio_checkbox.setChecked(True) # type: ignore
85
+ button_layout.addLayout(layout)
86
+
87
+ layout = QHBoxLayout()
88
+ self.add_label("xrange:", layout)
89
+ self.add_lineedit("xrange_min", layout, "xmin")
90
+ self.add_lineedit("xrange_max", layout, "xmax")
91
+ self.add_label("x-scale:", layout)
92
+ self.add_combobox("xscale_selector", layout, scales)
93
+ self.add_lineedit("xscale_tresh", layout, "x-tresh")
94
+ button_layout.addLayout(layout)
95
+
96
+ layout = QHBoxLayout()
97
+ self.add_label("yrange:", layout)
98
+ self.add_lineedit("yrange_min", layout, "ymin")
99
+ self.add_lineedit("yrange_max", layout, "ymax")
100
+ self.add_label("y-scale:", layout)
101
+ self.add_combobox("yscale_selector", layout, scales)
102
+ self.add_lineedit("yscale_tresh", layout, "y-tresh")
103
+ button_layout.addLayout(layout)
104
+
105
+ layout = QHBoxLayout()
106
+ self.add_label("vrange:", layout)
107
+ self.add_lineedit("vrange_min", layout, "vmin")
108
+ self.add_lineedit("vrange_max", layout, "vmax")
109
+ self.add_label("v-scale:", layout)
110
+ self.add_combobox("vscale_selector", layout, vscales)
111
+ self.add_lineedit("vscale_tresh", layout, "v-tresh")
112
+ button_layout.addLayout(layout)
113
+
114
+ layout = QHBoxLayout()
115
+ self.add_label("cmap:", layout)
116
+ self.add_combobox("typecmap_selector", layout, cmaps_divided.keys())
117
+ self.add_combobox("cmap_selector", layout, cmaps_avail)
118
+ self.add_checkbox("reverse", layout, "reverse_checkbox")
119
+ button_layout.addLayout(layout)
120
+
121
+ layout = QHBoxLayout()
122
+ self.add_pushbutton("Plot", layout, self.plot_data)
123
+ self.add_checkbox("Overplot ", layout, "overplot_checkbox")
124
+ button_layout.addLayout(layout)
125
+
126
+ layout = QHBoxLayout()
127
+ self.add_pushbutton("Update plot", layout, self.update_axes)
128
+ self.add_pushbutton("Clear", layout, self.clear_labels)
129
+ self.add_pushbutton("Reload Canvas", layout, self.reload_canvas)
130
+ button_layout.addLayout(layout)
131
+
132
+ self.add_line(button_layout)
133
+
134
+ info_box = QTextEdit()
135
+ info_box.setObjectName("info_label")
136
+ info_box.setReadOnly(True)
137
+ info_box.setFixedSize(370, 200) # keep your original fixed size
138
+ button_layout.addWidget(info_box)
139
+ self.info_label = info_box
140
+
141
+ self.add_line(button_layout)
142
+
143
+ main_layout.addLayout(button_layout)
144
+
145
+ self.typecmap_selector.currentIndexChanged.connect(
146
+ self.update_cmap_selector
147
+ ) # type: ignore
148
+
149
+ self.canvas_layout = QVBoxLayout()
150
+ self.create_new_figure()
151
+ main_layout.addLayout(self.canvas_layout)
152
+
153
+ from .config import (
154
+ _finalize_load_path,
155
+ clearload,
156
+ load_data,
157
+ reload_data,
158
+ select_folder,
159
+ )
160
+ from .panels import (
161
+ add_checkbox,
162
+ add_combobox,
163
+ add_label,
164
+ add_line,
165
+ add_lineedit,
166
+ add_pushbutton,
167
+ )
168
+ from .utils import (
169
+ check_axisparam,
170
+ clear_labels,
171
+ create_new_figure,
172
+ plot_data,
173
+ reload_canvas,
174
+ set_range,
175
+ update_axes,
176
+ update_cmap_selector,
177
+ )
pyPLUTO/gui/panels.py ADDED
@@ -0,0 +1,66 @@
1
+ """Utility functions to add common widgets to a layout."""
2
+
3
+ from PySide6.QtWidgets import (
4
+ QCheckBox,
5
+ QComboBox,
6
+ QFrame,
7
+ QLabel,
8
+ QLineEdit,
9
+ QPushButton,
10
+ )
11
+
12
+
13
+ def add_line(self, control_layout):
14
+ line = QFrame()
15
+ line.setFrameShape(QFrame.Shape.HLine)
16
+ line.setFrameShadow(QFrame.Shadow.Sunken)
17
+ control_layout.addWidget(line)
18
+
19
+
20
+ def add_combobox(self, label, control_layout, data, width=None, height=None):
21
+ combo_box = QComboBox()
22
+ setattr(self, label, combo_box)
23
+ combo_box.addItems(data)
24
+ if isinstance(width, int):
25
+ combo_box.setFixedWidth(width)
26
+ control_layout.addWidget(combo_box)
27
+
28
+
29
+ def add_label(self, label, control_layout, data=None, width=None, height=None):
30
+ labelgui = QLabel(label)
31
+ if isinstance(width, int):
32
+ labelgui.setFixedWidth(width)
33
+ if isinstance(height, int):
34
+ labelgui.setFixedHeight(height)
35
+ if data is not None:
36
+ setattr(self, data, labelgui)
37
+ control_layout.addWidget(labelgui)
38
+
39
+
40
+ def add_lineedit(
41
+ self, label, control_layout, data=None, width=None, height=None
42
+ ):
43
+ lineedit = QLineEdit()
44
+ setattr(self, label, lineedit)
45
+ lineedit.setPlaceholderText(data)
46
+ if isinstance(width, int):
47
+ lineedit.setFixedWidth(width)
48
+ control_layout.addWidget(lineedit)
49
+
50
+
51
+ def add_checkbox(
52
+ self, label, control_layout, data=None, width=None, height=None
53
+ ):
54
+ checkbox = QCheckBox(label)
55
+ if data is not None:
56
+ setattr(self, data, checkbox)
57
+ control_layout.addWidget(checkbox)
58
+
59
+
60
+ def add_pushbutton(self, label, control_layout, data=None, width=None):
61
+ pushbutton = QPushButton(label)
62
+ setattr(self, label, pushbutton)
63
+ if isinstance(width, int):
64
+ pushbutton.setFixedWidth(width)
65
+ pushbutton.clicked.connect(data) # type: ignore
66
+ control_layout.addWidget(pushbutton)
pyPLUTO/gui/utils.py ADDED
@@ -0,0 +1,273 @@
1
+ import matplotlib.pyplot as plt
2
+ import numpy as np
3
+ from matplotlib.backends.backend_qtagg import FigureCanvasQTAgg as FigureCanvas
4
+ from matplotlib.backends.backend_qtagg import (
5
+ NavigationToolbar2QT as NavigationToolbar,
6
+ )
7
+
8
+ import pyPLUTO as pp
9
+
10
+ from .globals import cmaps_divided as cmaps
11
+
12
+
13
+ def update_cmap_selector(self):
14
+ selected_type = self.typecmap_selector.currentText()
15
+ self.cmap_selector.clear()
16
+ self.cmap_selector.addItems(cmaps.get(selected_type, []))
17
+
18
+
19
+ def clear_labels(self):
20
+ self.var_selector.setCurrentIndex(0)
21
+ self.ratio_checkbox.setChecked(True)
22
+ self.transpose_checkbox.setChecked(False)
23
+ self.xaxis_selector.setCurrentIndex(0)
24
+ self.yaxis_selector.setCurrentIndex(0)
25
+ self.xslicetext.clear()
26
+ self.yslicetext.clear()
27
+ self.zslicetext.clear()
28
+ self.plot_title.clear()
29
+ self.xrange_min.clear()
30
+ self.xrange_max.clear()
31
+ self.yrange_min.clear()
32
+ self.yrange_max.clear()
33
+ self.vrange_min.clear()
34
+ self.vrange_max.clear()
35
+ self.xscale_selector.setCurrentIndex(0)
36
+ self.yscale_selector.setCurrentIndex(0)
37
+ self.vscale_selector.setCurrentIndex(0)
38
+ self.xscale_tresh.clear()
39
+ self.yscale_tresh.clear()
40
+ self.vscale_tresh.clear()
41
+ self.typecmap_selector.setCurrentIndex(0)
42
+ self.cmap_selector.setCurrentIndex(0)
43
+ self.reverse_checkbox.setChecked(False)
44
+ self.overplot_checkbox.setChecked(False)
45
+
46
+
47
+ def update_axes(self):
48
+ self.check_axisparam()
49
+ cmap = self.datadict.pop("cmap")
50
+ cscale = self.datadict.pop("cscale")
51
+ vmin = self.datadict.pop("vmin", self.var.min())
52
+ vmax = self.datadict.pop("vmax", self.var.max())
53
+ ctresh = self.datadict.pop("tresh", max(np.abs(vmin), vmax) * 0.01)
54
+ norm = self.I.ImageToolsManager.set_cscale(cscale, vmin, vmax, ctresh)
55
+ for artist in self.I.ax[0].get_children():
56
+ if isinstance(
57
+ artist,
58
+ (
59
+ plt.matplotlib.image.AxesImage,
60
+ plt.matplotlib.collections.QuadMesh,
61
+ ),
62
+ ):
63
+ artist.set_cmap(cmap)
64
+ artist.set_norm(norm)
65
+
66
+ self.set_range(xlim=None, ylim=None)
67
+ self.I.set_axis(self.I.ax[0], **self.datadict)
68
+ self.datadict["cmap"] = cmap
69
+ self.datadict["cscale"] = cscale
70
+ self.datadict["tresh"] = ctresh
71
+ self.canvas.figure = self.I.fig
72
+ self.canvas.draw()
73
+
74
+
75
+ def get_slice(text, axis_length):
76
+ try:
77
+ return eval(f"np.s_[{text}]", {"np": np, "axis_length": axis_length})
78
+ except Exception:
79
+ return int(text) if text.isdigit() else None
80
+
81
+
82
+ def plot_data(self):
83
+ if not self.data_loaded:
84
+ print("ERROR: No data loaded.")
85
+ return
86
+
87
+ var_name = self.var_selector.currentText()
88
+ if not var_name:
89
+ print("ERROR: No variable selected.")
90
+ return
91
+
92
+ self.var = getattr(self.D, var_name)
93
+
94
+ self.var = self.var.T if self.transpose_checkbox.isChecked() else self.var
95
+ # Apply slicing if a valid text is provided
96
+ if self.zslicetext.text() and np.ndim(self.var) == 3:
97
+ self.zslice = get_slice(self.zslicetext.text(), self.var.shape[2])
98
+ self.var = self.var[:, :, self.zslice]
99
+
100
+ if self.yslicetext.text() and np.ndim(self.var) > 1:
101
+ self.yslice = get_slice(self.yslicetext.text(), self.var.shape[1])
102
+ self.var = self.var[:, self.yslice]
103
+
104
+ if self.xslicetext.text():
105
+ self.xslice = get_slice(self.xslicetext.text(), self.var.shape[0])
106
+ self.var = self.var[self.xslice]
107
+
108
+ self.vardim = len(np.shape(self.var))
109
+ if self.vardim < 1 or self.vardim > 2:
110
+ raise ValueError("ERROR: Variable shape not recognized.")
111
+ self.check_axisparam()
112
+
113
+ if self.D.geom == "POLAR":
114
+ convert_axis = {
115
+ "R": "x1",
116
+ "phi": "x2",
117
+ "z": "x3",
118
+ "x": "x1c",
119
+ "y": "x2c",
120
+ }
121
+ elif self.D.geom == "SPHERICAL":
122
+ convert_axis = {
123
+ "r": "x1",
124
+ "theta": "x2",
125
+ "phi": "x3",
126
+ "R": "x1p",
127
+ "z": "x2p",
128
+ "rt": "x1t",
129
+ "zt": "x3t",
130
+ }
131
+ else:
132
+ convert_axis = {"x": "x1", "y": "x2", "z": "x3"}
133
+
134
+ axis_convert = {
135
+ key: (val if self.vardim == 1 else val[:2] + "r" + val[2:])
136
+ for key, val in convert_axis.items()
137
+ }
138
+
139
+ if self.overplot_checkbox.isChecked() and self.vardim == 1:
140
+ self.numlines = self.numlines + 1 if self.numlines > 0 else 1
141
+ else:
142
+ self.reload_canvas()
143
+ self.numlines = 1
144
+
145
+ x1 = getattr(self.D, axis_convert[self.xaxis_selector.currentText()])
146
+ x2 = getattr(self.D, axis_convert[self.yaxis_selector.currentText()])
147
+
148
+ xlim = [x1.min(), x1.max()]
149
+ ylim = (
150
+ [x2.min(), x2.max()]
151
+ if self.vardim == 2
152
+ else [self.var.min(), self.var.max()]
153
+ )
154
+
155
+ self.set_range(xlim, ylim)
156
+
157
+ if self.vardim == 1:
158
+ cmap_temp = self.datadict.pop("cmap")
159
+ cscale_temp = self.datadict.pop("cscale")
160
+ ctresh_temp = self.datadict.pop("tresh", None)
161
+ self.I.plot(x1, self.var, **self.datadict, xtitle=" ", ytitle=" ")
162
+ self.datadict["cmap"] = cmap_temp
163
+ self.datadict["cscale"] = cscale_temp
164
+ if ctresh_temp is not None:
165
+ self.datadict["tresh"] = ctresh_temp
166
+ elif self.vardim == 2:
167
+ self.I.display(
168
+ self.var,
169
+ x1=x1,
170
+ x2=x2,
171
+ cpos="right",
172
+ **self.datadict,
173
+ xtitle=" ",
174
+ ytitle=" ",
175
+ clabel=" ",
176
+ )
177
+
178
+ self.firstplot = False
179
+ self.canvas.draw()
180
+
181
+
182
+ def create_new_figure(self):
183
+ self.I = pp.Image(figsize=[10, 6])
184
+ self.firstplot = True
185
+ self.figure = self.I.fig
186
+ print(self.I.fontsize, self.I.figsize)
187
+
188
+ self.canvas = FigureCanvas(self.figure)
189
+ self.toolbar = NavigationToolbar(self.canvas, self)
190
+ self.canvas.setFixedWidth(800)
191
+
192
+ # Add a new toolbar and canvas to the layout
193
+ self.canvas_layout.addWidget(self.toolbar)
194
+ self.canvas_layout.addWidget(self.canvas)
195
+
196
+
197
+ def reload_canvas(self):
198
+ # Remove old toolbar and canvas
199
+ self.canvas_layout.removeWidget(self.toolbar)
200
+ self.toolbar.deleteLater()
201
+ self.canvas_layout.removeWidget(self.canvas)
202
+ self.canvas.deleteLater()
203
+ self.create_new_figure()
204
+
205
+
206
+ def check_axisparam(self):
207
+ self.datadict = {}
208
+ if self.vrange_min.text():
209
+ self.datadict["vmin"] = float(self.vrange_min.text())
210
+ if self.vrange_max.text():
211
+ self.datadict["vmax"] = float(self.vrange_max.text())
212
+
213
+ if not self.ratio_checkbox.isChecked():
214
+ self.datadict["aspect"] = "equal"
215
+ else:
216
+ self.datadict["aspect"] = "auto"
217
+
218
+ self.datadict["cmap"] = self.cmap_selector.currentText()
219
+ if self.reverse_checkbox.isChecked():
220
+ if self.datadict["cmap"][-2:] == "_r":
221
+ self.datadict["cmap"] = self.datadict["cmap"][:-2]
222
+ else:
223
+ self.datadict["cmap"] += "_r"
224
+
225
+ self.datadict["title"] = (
226
+ self.plot_title.text() if self.plot_title.text() else ""
227
+ )
228
+
229
+ self.datadict["xscale"] = self.xscale_selector.currentText()
230
+ if self.xscale_tresh.text():
231
+ self.datadict["xtresh"] = float(self.xscale_tresh.text())
232
+
233
+ self.datadict["yscale"] = self.yscale_selector.currentText()
234
+ if self.yscale_tresh.text():
235
+ self.datadict["ytresh"] = float(self.yscale_tresh.text())
236
+
237
+ self.datadict["cscale"] = self.vscale_selector.currentText()
238
+ if self.vscale_tresh.text():
239
+ self.datadict["tresh"] = float(self.vscale_tresh.text())
240
+
241
+
242
+ def set_range(self, xlim, ylim):
243
+ if xlim is None:
244
+ xlim = [self.xmin, self.xmax]
245
+ if ylim is None:
246
+ ylim = [self.ymin, self.ymax]
247
+
248
+ if self.firstplot is True:
249
+ self.xmin, self.xmax = xlim
250
+ self.ymin, self.ymax = ylim
251
+ else:
252
+ self.xmin = np.minimum(xlim[0], self.xmin)
253
+ self.xmax = np.maximum(xlim[1], self.xmax)
254
+ self.ymin = np.minimum(ylim[0], self.ymin)
255
+ self.ymax = np.maximum(ylim[1], self.ymax)
256
+
257
+ ymin, ymax = (
258
+ self.I.RangeManager.range_offset(
259
+ self.ymin, self.ymax, self.yscale_selector.currentText()
260
+ )
261
+ if self.vardim == 1
262
+ else (self.ymin, self.ymax)
263
+ )
264
+
265
+ self.datadict["xrange"] = [
266
+ float(self.xrange_min.text()) if self.xrange_min.text() else self.xmin,
267
+ float(self.xrange_max.text()) if self.xrange_max.text() else self.xmax,
268
+ ]
269
+
270
+ self.datadict["yrange"] = [
271
+ float(self.yrange_min.text()) if self.yrange_min.text() else ymin,
272
+ float(self.yrange_max.text()) if self.yrange_max.text() else ymax,
273
+ ]
pyPLUTO/h_pypluto.py ADDED
@@ -0,0 +1,84 @@
1
+ """Helper functions for pyPLUTO."""
2
+
3
+ import warnings
4
+
5
+
6
+ def makelist[T](el: T | list[T]) -> list[T]:
7
+ """If the element is not a list, it converts it into a list.
8
+
9
+ Returns
10
+ -------
11
+ - list[Any]
12
+ The list of chosen elements.
13
+
14
+ Parameters
15
+ ----------
16
+ - el (not optional): Any
17
+ The element to be converted into a list.
18
+
19
+ ----
20
+
21
+ Examples
22
+ --------
23
+ - Example #1: element is a list
24
+
25
+ >>> makelist([1, 2, 3])
26
+ [1,2,3]
27
+
28
+ - Example #2: element is not a list
29
+
30
+ >>> makelist(1)
31
+ [1]
32
+
33
+ """
34
+ # Return the element as a list
35
+ return el if isinstance(el, list) else [el]
36
+
37
+
38
+ def check_par(par: set[str], func: str, **kwargs: object) -> None:
39
+ """Check the kwargs of a PyPLUTO function/method.
40
+
41
+ Checks if a parameter is in the corresponding list depending on
42
+ the function. If the parameter does not belong to the list it raises
43
+ a warning.
44
+
45
+ Returns
46
+ -------
47
+ - None
48
+
49
+ Parameters
50
+ ----------
51
+ - func (not optional): str
52
+ The name of the function.
53
+ - par (not optional): list[str]
54
+ The function correct parameters.
55
+ - **kwargs: dict
56
+ The selected parameters.
57
+
58
+ ----
59
+
60
+ Examples
61
+ --------
62
+ - Example #1: check if the parameters are in the list (no warning)
63
+
64
+ **kwargs = {'a': 1, 'b': 2, 'c': 3}
65
+ >>> check_par({"a", "b", "c"}, "func", **kwargs)
66
+
67
+ - Example #2: check if the parameters are in the list (raises warning)
68
+
69
+ **kwargs = {'a': 1, 'd': 2, 'c': 3}
70
+ >>> check_par({"a", "b", "c"}, "func", **kwargs)
71
+
72
+ """
73
+ # Check if the parameters are in the list
74
+ notfound: list[str] = [(i) for i in kwargs if i not in par]
75
+
76
+ # If the parameters are not in the list, raise a warning
77
+ if len(notfound) > 0:
78
+ warn = (
79
+ f"WARNING: elements {notfound!s} not found!"
80
+ f"Please check your spelling! (function {func})"
81
+ )
82
+ warnings.warn(warn, UserWarning, stacklevel=2)
83
+
84
+ # End of the function