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.
- pyPLUTO/__init__.py +22 -0
- pyPLUTO/amr.py +745 -0
- pyPLUTO/baseloadmixin.py +258 -0
- pyPLUTO/baseloadstate.py +45 -0
- pyPLUTO/codes/echo_load.py +161 -0
- pyPLUTO/configure.py +261 -0
- pyPLUTO/gui/config.py +174 -0
- pyPLUTO/gui/custom_var.py +435 -0
- pyPLUTO/gui/globals.py +108 -0
- pyPLUTO/gui/main.py +17 -0
- pyPLUTO/gui/main_window.py +177 -0
- pyPLUTO/gui/panels.py +66 -0
- pyPLUTO/gui/utils.py +273 -0
- pyPLUTO/h_pypluto.py +84 -0
- pyPLUTO/image.py +302 -0
- pyPLUTO/imagefuncs/colorbar.py +240 -0
- pyPLUTO/imagefuncs/contour.py +254 -0
- pyPLUTO/imagefuncs/create_axes.py +464 -0
- pyPLUTO/imagefuncs/display.py +306 -0
- pyPLUTO/imagefuncs/figure.py +395 -0
- pyPLUTO/imagefuncs/imagetools.py +487 -0
- pyPLUTO/imagefuncs/interactive.py +403 -0
- pyPLUTO/imagefuncs/legend.py +250 -0
- pyPLUTO/imagefuncs/plot.py +311 -0
- pyPLUTO/imagefuncs/range.py +242 -0
- pyPLUTO/imagefuncs/scatter.py +270 -0
- pyPLUTO/imagefuncs/set_axis.py +497 -0
- pyPLUTO/imagefuncs/streamplot.py +297 -0
- pyPLUTO/imagefuncs/zoom.py +428 -0
- pyPLUTO/imagemixin.py +259 -0
- pyPLUTO/imagestate.py +45 -0
- pyPLUTO/load.py +447 -0
- pyPLUTO/loadfuncs/baseloadtools.py +71 -0
- pyPLUTO/loadfuncs/codeselection.py +48 -0
- pyPLUTO/loadfuncs/defpluto.py +123 -0
- pyPLUTO/loadfuncs/descriptor.py +102 -0
- pyPLUTO/loadfuncs/findfiles.py +182 -0
- pyPLUTO/loadfuncs/findformat.py +245 -0
- pyPLUTO/loadfuncs/initload.py +203 -0
- pyPLUTO/loadfuncs/loadvars.py +227 -0
- pyPLUTO/loadfuncs/offsetdata.py +87 -0
- pyPLUTO/loadfuncs/offsetfluid.py +408 -0
- pyPLUTO/loadfuncs/read_files.py +213 -0
- pyPLUTO/loadfuncs/readdata.py +619 -0
- pyPLUTO/loadfuncs/readdata_old.py +567 -0
- pyPLUTO/loadfuncs/readdefplini.py +101 -0
- pyPLUTO/loadfuncs/readfluid.py +479 -0
- pyPLUTO/loadfuncs/readformat.py +277 -0
- pyPLUTO/loadfuncs/readgridalone.py +224 -0
- pyPLUTO/loadfuncs/readgridfile.py +255 -0
- pyPLUTO/loadfuncs/readgridout.py +451 -0
- pyPLUTO/loadfuncs/readpart.py +419 -0
- pyPLUTO/loadfuncs/readtab.py +105 -0
- pyPLUTO/loadfuncs/write_files.py +283 -0
- pyPLUTO/loadmixin.py +419 -0
- pyPLUTO/loadpart.py +233 -0
- pyPLUTO/loadstate.py +68 -0
- pyPLUTO/newload.py +81 -0
- pyPLUTO/pytools.py +145 -0
- pyPLUTO/toolfuncs/findlines.py +551 -0
- pyPLUTO/toolfuncs/fourier.py +149 -0
- pyPLUTO/toolfuncs/nabla.py +676 -0
- pyPLUTO/toolfuncs/parttools.py +152 -0
- pyPLUTO/toolfuncs/transform.py +638 -0
- pyPLUTO/utils/annotator.py +27 -0
- pyPLUTO/utils/inspector.py +145 -0
- pyPLUTO/utils/make_docstrings.py +3 -0
- py_pluto-1.1.4.dist-info/METADATA +218 -0
- py_pluto-1.1.4.dist-info/RECORD +73 -0
- py_pluto-1.1.4.dist-info/WHEEL +5 -0
- py_pluto-1.1.4.dist-info/entry_points.txt +2 -0
- py_pluto-1.1.4.dist-info/licenses/LICENSE +27 -0
- 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
|