PQEnalyzer 0.6.2__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.
- PQEnalyzer/__init__.py +16 -0
- PQEnalyzer/__main__.py +85 -0
- PQEnalyzer/__version__.py +16 -0
- PQEnalyzer/apps/__init__.py +5 -0
- PQEnalyzer/apps/app.py +409 -0
- PQEnalyzer/apps/termapp.py +100 -0
- PQEnalyzer/icons/icon.png +0 -0
- PQEnalyzer/plots/__init__.py +7 -0
- PQEnalyzer/plots/plot.py +256 -0
- PQEnalyzer/plots/plot_histogram.py +165 -0
- PQEnalyzer/plots/plot_time.py +181 -0
- PQEnalyzer/plots/termplot.py +65 -0
- PQEnalyzer/readers/__init__.py +4 -0
- PQEnalyzer/readers/reader.py +119 -0
- PQEnalyzer/statistics/__init__.py +4 -0
- PQEnalyzer/statistics/statistic.py +238 -0
- PQEnalyzer-0.6.2.dist-info/LICENSE +21 -0
- PQEnalyzer-0.6.2.dist-info/METADATA +53 -0
- PQEnalyzer-0.6.2.dist-info/RECORD +22 -0
- PQEnalyzer-0.6.2.dist-info/WHEEL +5 -0
- PQEnalyzer-0.6.2.dist-info/entry_points.txt +2 -0
- PQEnalyzer-0.6.2.dist-info/top_level.txt +1 -0
PQEnalyzer/__init__.py
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"""
|
|
2
|
+
This is the main module of the package. It is used to import the
|
|
3
|
+
main classes and functions of the package.
|
|
4
|
+
"""
|
|
5
|
+
import sys
|
|
6
|
+
|
|
7
|
+
# beartype
|
|
8
|
+
from beartype.claw import beartype_this_package
|
|
9
|
+
|
|
10
|
+
beartype_this_package()
|
|
11
|
+
|
|
12
|
+
# zero traceback limit
|
|
13
|
+
# sys.tracebacklimit = 0
|
|
14
|
+
|
|
15
|
+
# base path
|
|
16
|
+
__base__ = __file__.split("/__init__.py")[0]
|
PQEnalyzer/__main__.py
ADDED
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
"""
|
|
2
|
+
This is the main file of the PQEnalyzer project. It contains the
|
|
3
|
+
main function that is executed when the program is run.
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
import sys
|
|
7
|
+
import argparse
|
|
8
|
+
import argcomplete
|
|
9
|
+
from PQAnalysis.traj import MDEngineFormat
|
|
10
|
+
|
|
11
|
+
from .__version__ import __version__
|
|
12
|
+
from .apps import App, TermApp
|
|
13
|
+
from .readers import Reader
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def main():
|
|
17
|
+
"""
|
|
18
|
+
The main function of the PQEnalyzer project. It reads the data
|
|
19
|
+
from the energy files and plots the data in the GUI or in the terminal.
|
|
20
|
+
Use the -h or --help flag to see the command line arguments.
|
|
21
|
+
|
|
22
|
+
Parameters
|
|
23
|
+
----------
|
|
24
|
+
None
|
|
25
|
+
|
|
26
|
+
Returns
|
|
27
|
+
-------
|
|
28
|
+
None
|
|
29
|
+
"""
|
|
30
|
+
# parse command line arguments
|
|
31
|
+
parser = argparse.ArgumentParser(description="PQEnalyzer - MolarVerse")
|
|
32
|
+
parser.add_argument(
|
|
33
|
+
"filenames",
|
|
34
|
+
metavar="filenames",
|
|
35
|
+
nargs="+",
|
|
36
|
+
help="The name of the energy files to read the data from.")
|
|
37
|
+
parser.add_argument("-q",
|
|
38
|
+
"--qmcfc",
|
|
39
|
+
action="store_true",
|
|
40
|
+
help="Use the QMCFC output as input.")
|
|
41
|
+
parser.add_argument("-n",
|
|
42
|
+
"--no-gui",
|
|
43
|
+
action="store_true",
|
|
44
|
+
help="Opens the terminal plotting feature.")
|
|
45
|
+
parser.add_argument("-v",
|
|
46
|
+
"--version",
|
|
47
|
+
action="version",
|
|
48
|
+
version=f"PQEnalyzer {__version__}")
|
|
49
|
+
|
|
50
|
+
# autocomplete the command line arguments
|
|
51
|
+
argcomplete.autocomplete(parser)
|
|
52
|
+
|
|
53
|
+
# get command line arguments
|
|
54
|
+
filenames = parser.parse_args().filenames
|
|
55
|
+
|
|
56
|
+
# set the md format
|
|
57
|
+
md_format = MDEngineFormat.PQ
|
|
58
|
+
|
|
59
|
+
# if the user wants to use the QMCFC output as input
|
|
60
|
+
if parser.parse_args().qmcfc:
|
|
61
|
+
md_format = MDEngineFormat.QMCFC # set the md format to QMCFC
|
|
62
|
+
|
|
63
|
+
# create the reader
|
|
64
|
+
try:
|
|
65
|
+
reader = Reader(filenames, md_format)
|
|
66
|
+
except Exception as e:
|
|
67
|
+
print(e)
|
|
68
|
+
sys.exit(1)
|
|
69
|
+
|
|
70
|
+
# if the user wants to use the terminal plotting feature
|
|
71
|
+
if parser.parse_args().no_gui:
|
|
72
|
+
# create the termplot
|
|
73
|
+
termapp = TermApp(reader)
|
|
74
|
+
termapp.start()
|
|
75
|
+
else:
|
|
76
|
+
# create the app
|
|
77
|
+
app = App(reader)
|
|
78
|
+
app.build()
|
|
79
|
+
app.mainloop()
|
|
80
|
+
|
|
81
|
+
return None
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
if __name__ == "__main__":
|
|
85
|
+
main()
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# file generated by setuptools_scm
|
|
2
|
+
# don't change, don't track in version control
|
|
3
|
+
TYPE_CHECKING = False
|
|
4
|
+
if TYPE_CHECKING:
|
|
5
|
+
from typing import Tuple, Union
|
|
6
|
+
VERSION_TUPLE = Tuple[Union[int, str], ...]
|
|
7
|
+
else:
|
|
8
|
+
VERSION_TUPLE = object
|
|
9
|
+
|
|
10
|
+
version: str
|
|
11
|
+
__version__: str
|
|
12
|
+
__version_tuple__: VERSION_TUPLE
|
|
13
|
+
version_tuple: VERSION_TUPLE
|
|
14
|
+
|
|
15
|
+
__version__ = version = '0.6.2'
|
|
16
|
+
__version_tuple__ = version_tuple = (0, 6, 2)
|
PQEnalyzer/apps/app.py
ADDED
|
@@ -0,0 +1,409 @@
|
|
|
1
|
+
"""
|
|
2
|
+
This module contains the App class that is used to create the main application
|
|
3
|
+
window for the PQEnalyzer application.
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
import os
|
|
7
|
+
import signal
|
|
8
|
+
import tkinter
|
|
9
|
+
|
|
10
|
+
import customtkinter as ctk
|
|
11
|
+
from PIL import Image, ImageTk
|
|
12
|
+
import matplotlib.pyplot as plt
|
|
13
|
+
|
|
14
|
+
from .. import __base__
|
|
15
|
+
from ..plots import PlotTime, PlotHistogram
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class App(ctk.CTk):
|
|
19
|
+
"""
|
|
20
|
+
The main application class for the PQEnalyzer application. This class inherits
|
|
21
|
+
from the CTK class.
|
|
22
|
+
|
|
23
|
+
...
|
|
24
|
+
|
|
25
|
+
Attributes
|
|
26
|
+
----------
|
|
27
|
+
reader : Reader
|
|
28
|
+
The reader object that contains the data.
|
|
29
|
+
|
|
30
|
+
Methods
|
|
31
|
+
-------
|
|
32
|
+
build()
|
|
33
|
+
Build the main window.
|
|
34
|
+
"""
|
|
35
|
+
|
|
36
|
+
def __init__(self, reader=None):
|
|
37
|
+
"""
|
|
38
|
+
Constructs all the necessary attributes for the App object.
|
|
39
|
+
"""
|
|
40
|
+
super().__init__()
|
|
41
|
+
self.__default_theme()
|
|
42
|
+
self.title("PQEnalyzer - MolarVerse")
|
|
43
|
+
|
|
44
|
+
# load icon photo
|
|
45
|
+
img = Image.open(os.path.join(__base__, "icons", "icon.png"))
|
|
46
|
+
self.iconphoto(False, ImageTk.PhotoImage(img))
|
|
47
|
+
|
|
48
|
+
# set the window size
|
|
49
|
+
self.resizable(False, False)
|
|
50
|
+
|
|
51
|
+
# set reader object and info parameters
|
|
52
|
+
self.reader = reader
|
|
53
|
+
self.info = [
|
|
54
|
+
*self.reader.energies[0].info
|
|
55
|
+
][1:] # get list of info parameters from first data object
|
|
56
|
+
|
|
57
|
+
self.list_of_plots = []
|
|
58
|
+
|
|
59
|
+
# sigint handler
|
|
60
|
+
signal.signal(signal.SIGINT,
|
|
61
|
+
lambda sig, frame: self.destroy()) # close the app
|
|
62
|
+
|
|
63
|
+
def destroy(self):
|
|
64
|
+
"""
|
|
65
|
+
Destroy the app.
|
|
66
|
+
"""
|
|
67
|
+
self.quit()
|
|
68
|
+
del (self)
|
|
69
|
+
|
|
70
|
+
def build(self):
|
|
71
|
+
"""
|
|
72
|
+
Build the main window.
|
|
73
|
+
"""
|
|
74
|
+
self.__build_sidebar()
|
|
75
|
+
self.__build_button_menu()
|
|
76
|
+
self.__build_info_option_menu()
|
|
77
|
+
self.__build_settings_menu()
|
|
78
|
+
|
|
79
|
+
def __default_theme(self):
|
|
80
|
+
"""
|
|
81
|
+
Sets the default theme for the application.
|
|
82
|
+
"""
|
|
83
|
+
ctk.set_appearance_mode("System")
|
|
84
|
+
ctk.set_default_color_theme("blue")
|
|
85
|
+
|
|
86
|
+
def __build_sidebar(self):
|
|
87
|
+
"""
|
|
88
|
+
Build the main window.
|
|
89
|
+
|
|
90
|
+
Returns
|
|
91
|
+
-------
|
|
92
|
+
None
|
|
93
|
+
"""
|
|
94
|
+
# sidebar frame
|
|
95
|
+
self.sidebar_frame = ctk.CTkFrame(self, width=140, corner_radius=0)
|
|
96
|
+
self.sidebar_frame.grid(row=0, column=0, rowspan=4, sticky="nsew")
|
|
97
|
+
self.sidebar_frame.grid_rowconfigure(4, weight=1)
|
|
98
|
+
self.sidebar_frame.grid_columnconfigure(0, weight=1)
|
|
99
|
+
|
|
100
|
+
# logo
|
|
101
|
+
self.logo = ctk.CTkImage(
|
|
102
|
+
Image.open(os.path.join(__base__, "icons", "icon.png")),
|
|
103
|
+
size=(100, 100),
|
|
104
|
+
)
|
|
105
|
+
self.sidebar_image_label = ctk.CTkLabel(self.sidebar_frame,
|
|
106
|
+
image=self.logo,
|
|
107
|
+
text="")
|
|
108
|
+
self.sidebar_image_label.grid(row=0, column=0, pady=10, padx=10)
|
|
109
|
+
self.logo_label = ctk.CTkLabel(
|
|
110
|
+
self.sidebar_frame,
|
|
111
|
+
text="PQEnalyzer",
|
|
112
|
+
font=ctk.CTkFont(size=20, weight="bold"),
|
|
113
|
+
)
|
|
114
|
+
self.logo_label.grid(row=1, column=0, padx=10, pady=10)
|
|
115
|
+
|
|
116
|
+
# change appearance mode
|
|
117
|
+
self.appearance_mode_label = ctk.CTkLabel(self.sidebar_frame,
|
|
118
|
+
text="Appearance Mode:",
|
|
119
|
+
anchor="w")
|
|
120
|
+
self.appearance_mode_label.grid(row=5, column=0, padx=20, pady=(10, 0))
|
|
121
|
+
self.appearance_mode_optionemenu = ctk.CTkOptionMenu(
|
|
122
|
+
self.sidebar_frame,
|
|
123
|
+
values=["System", "Light", "Dark"],
|
|
124
|
+
command=self.__change_appearance_mode_event,
|
|
125
|
+
)
|
|
126
|
+
self.appearance_mode_optionemenu.grid(row=6,
|
|
127
|
+
column=0,
|
|
128
|
+
padx=20,
|
|
129
|
+
pady=(10, 10))
|
|
130
|
+
self.appearance_mode_optionemenu.set(
|
|
131
|
+
"System") # set the default appearance mode to System
|
|
132
|
+
|
|
133
|
+
def __build_button_menu(self):
|
|
134
|
+
"""
|
|
135
|
+
Build the main window.
|
|
136
|
+
|
|
137
|
+
Returns
|
|
138
|
+
-------
|
|
139
|
+
None
|
|
140
|
+
"""
|
|
141
|
+
self.plot_frame = ctk.CTkFrame(self, width=200)
|
|
142
|
+
self.plot_frame.grid(row=2,
|
|
143
|
+
column=1,
|
|
144
|
+
sticky="nsew",
|
|
145
|
+
padx=(20, 20),
|
|
146
|
+
pady=(10, 10))
|
|
147
|
+
self.plot_frame.grid_rowconfigure(4, weight=1)
|
|
148
|
+
self.plot_frame.grid_columnconfigure(2, weight=1)
|
|
149
|
+
|
|
150
|
+
self.follow = tkinter.BooleanVar()
|
|
151
|
+
self.interval = None # Initially None
|
|
152
|
+
self.check_follow = ctk.CTkCheckBox(
|
|
153
|
+
master=self.plot_frame,
|
|
154
|
+
border_width=2,
|
|
155
|
+
text="Follow",
|
|
156
|
+
variable=self.follow,
|
|
157
|
+
command=lambda: self.toggle_entry_state(
|
|
158
|
+
self.check_follow, self.interval, default="1.0"))
|
|
159
|
+
self.check_follow.grid(row=0,
|
|
160
|
+
column=1,
|
|
161
|
+
padx=(10, 10),
|
|
162
|
+
pady=(10, 10),
|
|
163
|
+
sticky="nsew")
|
|
164
|
+
|
|
165
|
+
self.plot_main_data = tkinter.BooleanVar()
|
|
166
|
+
self.check_nodata = ctk.CTkCheckBox(
|
|
167
|
+
master=self.plot_frame,
|
|
168
|
+
border_width=2,
|
|
169
|
+
text="No Data",
|
|
170
|
+
variable=self.plot_main_data,
|
|
171
|
+
)
|
|
172
|
+
self.check_nodata.grid(row=0,
|
|
173
|
+
column=0,
|
|
174
|
+
padx=(10, 10),
|
|
175
|
+
pady=(10, 10),
|
|
176
|
+
sticky="nsew")
|
|
177
|
+
|
|
178
|
+
self.interval = ctk.CTkEntry(
|
|
179
|
+
self.plot_frame,
|
|
180
|
+
width=10,
|
|
181
|
+
validate="key",
|
|
182
|
+
validatecommand=(self.register(self.validate_number), "%P"),
|
|
183
|
+
)
|
|
184
|
+
self.interval.grid(row=1, column=1, padx=10, pady=5, sticky="we")
|
|
185
|
+
self.interval.configure(state="disabled") # Initially disabled
|
|
186
|
+
|
|
187
|
+
self.interval_label = ctk.CTkLabel(self.plot_frame,
|
|
188
|
+
text="Interval (s):",
|
|
189
|
+
anchor="w")
|
|
190
|
+
self.interval_label.grid(row=1, column=0, padx=10, pady=5, sticky="w")
|
|
191
|
+
|
|
192
|
+
self.button_plot = ctk.CTkButton(
|
|
193
|
+
master=self.plot_frame,
|
|
194
|
+
fg_color="transparent",
|
|
195
|
+
border_width=2,
|
|
196
|
+
text_color=("gray10", "#DCE4EE"),
|
|
197
|
+
text="Plot",
|
|
198
|
+
command=lambda: self.__plot_button_event(0),
|
|
199
|
+
)
|
|
200
|
+
|
|
201
|
+
self.button_plot.grid(row=2,
|
|
202
|
+
column=0,
|
|
203
|
+
columnspan=2,
|
|
204
|
+
padx=(10, 10),
|
|
205
|
+
pady=(10, 10),
|
|
206
|
+
sticky="nsew")
|
|
207
|
+
|
|
208
|
+
self.button_hist = ctk.CTkButton(
|
|
209
|
+
master=self.plot_frame,
|
|
210
|
+
fg_color="transparent",
|
|
211
|
+
border_width=2,
|
|
212
|
+
text_color=("gray10", "#DCE4EE"),
|
|
213
|
+
text="Histogram",
|
|
214
|
+
command=lambda: self.__plot_button_event(1),
|
|
215
|
+
)
|
|
216
|
+
self.button_hist.grid(row=3,
|
|
217
|
+
column=0,
|
|
218
|
+
columnspan=2,
|
|
219
|
+
padx=(10, 10),
|
|
220
|
+
pady=(10, 10),
|
|
221
|
+
sticky="nsew")
|
|
222
|
+
|
|
223
|
+
self.button_refresh = ctk.CTkButton( # refresh button
|
|
224
|
+
master=self.plot_frame,
|
|
225
|
+
fg_color="transparent",
|
|
226
|
+
border_width=2,
|
|
227
|
+
text_color=("gray10", "#DCE4EE"),
|
|
228
|
+
text="Refresh",
|
|
229
|
+
command=self.__refresh_plots,
|
|
230
|
+
)
|
|
231
|
+
self.button_refresh.grid(row=4,
|
|
232
|
+
column=0,
|
|
233
|
+
columnspan=2,
|
|
234
|
+
padx=(10, 10),
|
|
235
|
+
pady=(10, 10),
|
|
236
|
+
sticky="nsew")
|
|
237
|
+
|
|
238
|
+
def __build_info_option_menu(self):
|
|
239
|
+
"""
|
|
240
|
+
Build the info selection window.
|
|
241
|
+
|
|
242
|
+
Returns
|
|
243
|
+
-------
|
|
244
|
+
None
|
|
245
|
+
"""
|
|
246
|
+
self.info_frame = ctk.CTkFrame(self, width=200)
|
|
247
|
+
self.info_frame.grid(row=0,
|
|
248
|
+
column=1,
|
|
249
|
+
sticky="nsew",
|
|
250
|
+
padx=(20, 20),
|
|
251
|
+
pady=(10, 10))
|
|
252
|
+
self.info_frame.grid_rowconfigure(2, weight=1)
|
|
253
|
+
self.info_frame.grid_columnconfigure(1, weight=1)
|
|
254
|
+
|
|
255
|
+
self.info_label = ctk.CTkLabel(self.info_frame,
|
|
256
|
+
text="Parameter:",
|
|
257
|
+
font=ctk.CTkFont(size=15,
|
|
258
|
+
weight="bold"))
|
|
259
|
+
self.info_label.grid(row=0, column=1, padx=20, pady=10, sticky="w")
|
|
260
|
+
self.info_optionmenu = ctk.CTkOptionMenu(
|
|
261
|
+
self.info_frame,
|
|
262
|
+
values=self.info,
|
|
263
|
+
command=self.__change_info_event,
|
|
264
|
+
width=150,
|
|
265
|
+
anchor="c",
|
|
266
|
+
)
|
|
267
|
+
self.info_optionmenu.grid(row=1, column=1, padx=20, pady=10)
|
|
268
|
+
self.__change_info_event(
|
|
269
|
+
self.info[0]) # set the default info parameter to the first one
|
|
270
|
+
|
|
271
|
+
def __build_settings_menu(self):
|
|
272
|
+
"""
|
|
273
|
+
Build the settings window.
|
|
274
|
+
|
|
275
|
+
Returns
|
|
276
|
+
-------
|
|
277
|
+
None
|
|
278
|
+
"""
|
|
279
|
+
self.settings_frame = ctk.CTkFrame(self, width=200)
|
|
280
|
+
self.settings_frame.grid(row=1,
|
|
281
|
+
column=1,
|
|
282
|
+
sticky="nsew",
|
|
283
|
+
padx=(20, 20),
|
|
284
|
+
pady=(10, 10))
|
|
285
|
+
self.settings_frame.grid_rowconfigure(8, weight=1)
|
|
286
|
+
self.settings_frame.grid_columnconfigure(0, weight=1)
|
|
287
|
+
|
|
288
|
+
self.settings_label = ctk.CTkLabel(
|
|
289
|
+
self.settings_frame,
|
|
290
|
+
text="Statistics:",
|
|
291
|
+
font=ctk.CTkFont(size=15, weight="bold"),
|
|
292
|
+
)
|
|
293
|
+
self.settings_label.grid(row=0, column=0, padx=10, pady=5, sticky="w")
|
|
294
|
+
self.mean = ctk.CTkCheckBox(self.settings_frame, text="Mean")
|
|
295
|
+
self.mean.grid(row=1, column=0, padx=10, pady=5, sticky="w")
|
|
296
|
+
self.median = ctk.CTkCheckBox(self.settings_frame, text="Median")
|
|
297
|
+
self.median.grid(row=2, column=0, padx=10, pady=5, sticky="w")
|
|
298
|
+
self.cummulative_average = ctk.CTkCheckBox(self.settings_frame,
|
|
299
|
+
text="Cummulative Average")
|
|
300
|
+
self.cummulative_average.grid(row=3,
|
|
301
|
+
column=0,
|
|
302
|
+
padx=10,
|
|
303
|
+
pady=5,
|
|
304
|
+
sticky="w")
|
|
305
|
+
self.auto_correlation = ctk.CTkCheckBox(self.settings_frame,
|
|
306
|
+
text="Auto Correlation")
|
|
307
|
+
self.auto_correlation.grid(row=4,
|
|
308
|
+
column=0,
|
|
309
|
+
padx=10,
|
|
310
|
+
pady=5,
|
|
311
|
+
sticky="w")
|
|
312
|
+
|
|
313
|
+
self.window_size = None # Initially None
|
|
314
|
+
self.running_average = ctk.CTkCheckBox(
|
|
315
|
+
self.settings_frame,
|
|
316
|
+
text="Running Average",
|
|
317
|
+
command=lambda: self.toggle_entry_state(
|
|
318
|
+
self.running_average, self.window_size, default="10"))
|
|
319
|
+
self.running_average.grid(row=5, column=0, padx=10, pady=5, sticky="w")
|
|
320
|
+
self.running_average_window_size_label = ctk.CTkLabel(
|
|
321
|
+
self.settings_frame, text="Window Size:", anchor="w")
|
|
322
|
+
self.running_average_window_size_label.grid(row=6,
|
|
323
|
+
column=0,
|
|
324
|
+
padx=10,
|
|
325
|
+
pady=5,
|
|
326
|
+
sticky="w")
|
|
327
|
+
self.window_size = ctk.CTkEntry(
|
|
328
|
+
self.settings_frame,
|
|
329
|
+
width=10,
|
|
330
|
+
validate="key",
|
|
331
|
+
validatecommand=(self.register(self.validate_number), "%P"),
|
|
332
|
+
)
|
|
333
|
+
self.window_size.grid(row=7, column=0, padx=10, pady=5, sticky="we")
|
|
334
|
+
self.window_size.configure(state="disabled") # Initially disabled
|
|
335
|
+
|
|
336
|
+
def validate_number(self, value):
|
|
337
|
+
"""
|
|
338
|
+
Validate if the input is a number.
|
|
339
|
+
"""
|
|
340
|
+
return value == "" or value.replace(".", "", 1).isdigit()
|
|
341
|
+
|
|
342
|
+
def toggle_entry_state(self, event, entry, default=""):
|
|
343
|
+
"""
|
|
344
|
+
Toggle the state of the entry.
|
|
345
|
+
"""
|
|
346
|
+
if event.get():
|
|
347
|
+
entry.configure(state="normal")
|
|
348
|
+
entry.insert(0, default)
|
|
349
|
+
else:
|
|
350
|
+
entry.delete(0, ctk.END)
|
|
351
|
+
entry.configure(state="disabled")
|
|
352
|
+
|
|
353
|
+
def __change_appearance_mode_event(self, new_appearance_mode: str):
|
|
354
|
+
"""
|
|
355
|
+
Change the appearance mode of the app.
|
|
356
|
+
"""
|
|
357
|
+
|
|
358
|
+
ctk.set_appearance_mode(new_appearance_mode)
|
|
359
|
+
|
|
360
|
+
def __change_info_event(self, new_info: str):
|
|
361
|
+
"""
|
|
362
|
+
Change the info parameter to plot.
|
|
363
|
+
"""
|
|
364
|
+
|
|
365
|
+
self.__selected_info = new_info
|
|
366
|
+
|
|
367
|
+
def __refresh_plots(self):
|
|
368
|
+
"""
|
|
369
|
+
Refresh the plots. If the plot is closed, remove it from the list.
|
|
370
|
+
|
|
371
|
+
Returns
|
|
372
|
+
-------
|
|
373
|
+
None
|
|
374
|
+
"""
|
|
375
|
+
for plot in self.list_of_plots:
|
|
376
|
+
|
|
377
|
+
if plot.figure.number not in plt.get_fignums():
|
|
378
|
+
self.list_of_plots.remove(plot)
|
|
379
|
+
continue
|
|
380
|
+
|
|
381
|
+
plot.refresh()
|
|
382
|
+
|
|
383
|
+
def __plot_button_event(self, event):
|
|
384
|
+
"""
|
|
385
|
+
Plot the data and checks if the user wants to follow the plot.
|
|
386
|
+
Appends the plot to the list of plots. If the user wants to follow the plot,
|
|
387
|
+
the plot is updated at a given interval.
|
|
388
|
+
|
|
389
|
+
Parameters
|
|
390
|
+
----------
|
|
391
|
+
event : int
|
|
392
|
+
The event that triggered the function. 0 for time plot, 1 for histogram plot.
|
|
393
|
+
|
|
394
|
+
Returns
|
|
395
|
+
-------
|
|
396
|
+
None
|
|
397
|
+
"""
|
|
398
|
+
|
|
399
|
+
if event == 0:
|
|
400
|
+
plot = PlotTime(self)
|
|
401
|
+
elif event == 1:
|
|
402
|
+
plot = PlotHistogram(self)
|
|
403
|
+
|
|
404
|
+
self.list_of_plots.append(plot)
|
|
405
|
+
|
|
406
|
+
if self.follow.get():
|
|
407
|
+
plot.follow(self.__selected_info, float(self.interval.get()))
|
|
408
|
+
else:
|
|
409
|
+
plot.simple(self.__selected_info)
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
"""
|
|
2
|
+
This module allows the user to plot the data in the terminal.
|
|
3
|
+
"""
|
|
4
|
+
import signal
|
|
5
|
+
from InquirerPy import inquirer
|
|
6
|
+
|
|
7
|
+
from ..plots import TermPlot
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class TermApp:
|
|
11
|
+
"""
|
|
12
|
+
A class to plot the data in the terminal.
|
|
13
|
+
|
|
14
|
+
Attributes
|
|
15
|
+
----------
|
|
16
|
+
reader : Reader
|
|
17
|
+
The Reader object to read the data.
|
|
18
|
+
|
|
19
|
+
Methods
|
|
20
|
+
-------
|
|
21
|
+
"""
|
|
22
|
+
|
|
23
|
+
def __init__(self, reader):
|
|
24
|
+
"""
|
|
25
|
+
Constructs all the necessary attributes for the TermApp object.
|
|
26
|
+
|
|
27
|
+
Parameters
|
|
28
|
+
----------
|
|
29
|
+
reader : Reader
|
|
30
|
+
The Reader object to read the data.
|
|
31
|
+
|
|
32
|
+
Returns
|
|
33
|
+
-------
|
|
34
|
+
None
|
|
35
|
+
"""
|
|
36
|
+
|
|
37
|
+
self.reader = reader
|
|
38
|
+
self.info = [
|
|
39
|
+
*self.reader.energies[0].info,
|
|
40
|
+
][1:]
|
|
41
|
+
|
|
42
|
+
return None
|
|
43
|
+
|
|
44
|
+
def run(self):
|
|
45
|
+
"""
|
|
46
|
+
Run the terminal application.
|
|
47
|
+
|
|
48
|
+
Parameters
|
|
49
|
+
----------
|
|
50
|
+
None
|
|
51
|
+
|
|
52
|
+
Returns
|
|
53
|
+
-------
|
|
54
|
+
None
|
|
55
|
+
"""
|
|
56
|
+
|
|
57
|
+
result = inquirer.select(
|
|
58
|
+
message="Select the information parameter to plot",
|
|
59
|
+
choices=self.info,
|
|
60
|
+
vi_mode=True,
|
|
61
|
+
mandatory=True,
|
|
62
|
+
).execute()
|
|
63
|
+
|
|
64
|
+
termplot = TermPlot(self.reader)
|
|
65
|
+
termplot.plot(result)
|
|
66
|
+
|
|
67
|
+
return None
|
|
68
|
+
|
|
69
|
+
def start(self):
|
|
70
|
+
"""
|
|
71
|
+
Start the terminal application.
|
|
72
|
+
|
|
73
|
+
Parameters
|
|
74
|
+
----------
|
|
75
|
+
None
|
|
76
|
+
|
|
77
|
+
Returns
|
|
78
|
+
-------
|
|
79
|
+
None
|
|
80
|
+
"""
|
|
81
|
+
try:
|
|
82
|
+
self.run()
|
|
83
|
+
_exit = inquirer.confirm(
|
|
84
|
+
message="Do you want to exit?",
|
|
85
|
+
default=False,
|
|
86
|
+
vi_mode=True,
|
|
87
|
+
keybindings={
|
|
88
|
+
"interrupt": [{
|
|
89
|
+
"key": "c-d"
|
|
90
|
+
}]
|
|
91
|
+
},
|
|
92
|
+
).execute()
|
|
93
|
+
|
|
94
|
+
if _exit:
|
|
95
|
+
return None
|
|
96
|
+
|
|
97
|
+
except KeyboardInterrupt:
|
|
98
|
+
return None
|
|
99
|
+
|
|
100
|
+
return self.start()
|
|
Binary file
|