ephys-link 2.0.0b6__py3-none-any.whl → 2.0.0b9__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.
@@ -1,215 +1,204 @@
1
- """Graphical User Interface for Ephys Link.
2
-
3
- Usage: create a GUI instance and call get_options() to get the options.
4
- """
5
-
6
- from json import load
7
- from os import makedirs
8
- from os.path import exists, join
9
- from socket import gethostbyname, gethostname
10
- from sys import exit
11
- from tkinter import CENTER, RIGHT, BooleanVar, E, IntVar, StringVar, Tk, ttk
12
-
13
- from platformdirs import user_config_dir
14
- from vbl_aquarium.models.ephys_link import EphysLinkOptions
15
-
16
- from ephys_link.__about__ import __version__ as version
17
-
18
- # Define options path.
19
- OPTIONS_DIR = join(user_config_dir(), "VBL", "Ephys Link")
20
- OPTIONS_FILENAME = "options.json"
21
- OPTIONS_PATH = join(OPTIONS_DIR, OPTIONS_FILENAME)
22
-
23
-
24
- class GUI:
25
- """Graphical User Interface for Ephys Link.
26
-
27
- Gathers options from the user and saves them to a file.
28
- """
29
-
30
- def __init__(self) -> None:
31
- """Setup GUI properties."""
32
-
33
- self._root = Tk()
34
-
35
- # Create default options.
36
- options = EphysLinkOptions()
37
-
38
- # Read options.
39
- if exists(OPTIONS_PATH):
40
- with open(OPTIONS_PATH) as options_file:
41
- options = EphysLinkOptions(**load(options_file))
42
-
43
- # Load options into GUI variables.
44
- self._ignore_updates = BooleanVar(value=options.ignore_updates)
45
- self._type = StringVar(value=options.type)
46
- self._debug = BooleanVar(value=options.debug)
47
- self._use_proxy = BooleanVar(value=options.use_proxy)
48
- self._proxy_address = StringVar(value=options.proxy_address)
49
- self._mpm_port = IntVar(value=options.mpm_port)
50
- self._serial = StringVar(value=options.serial)
51
-
52
- # Submit flag.
53
- self._submit = False
54
-
55
- def get_options(self) -> EphysLinkOptions:
56
- """Get options from GUI."""
57
-
58
- # Launch GUI.
59
- self._build_gui()
60
- self._root.mainloop()
61
-
62
- # Exit if the user did not submit options.
63
- if not self._submit:
64
- exit(1)
65
-
66
- # Extract options from GUI.
67
- options = EphysLinkOptions(
68
- ignore_updates=self._ignore_updates.get(),
69
- type=self._type.get(),
70
- debug=self._debug.get(),
71
- use_proxy=self._use_proxy.get(),
72
- proxy_address=self._proxy_address.get(),
73
- mpm_port=self._mpm_port.get(),
74
- serial=self._serial.get(),
75
- )
76
-
77
- # Save options.
78
- makedirs(OPTIONS_DIR, exist_ok=True)
79
- with open(OPTIONS_PATH, "w+") as options_file:
80
- options_file.write(options.model_dump_json())
81
-
82
- # Return options
83
- return options
84
-
85
- def _build_gui(self) -> None:
86
- """Build GUI."""
87
-
88
- self._root.title(f"Ephys Link v{version}")
89
-
90
- mainframe = ttk.Frame(self._root, padding=3)
91
- mainframe.grid(column=0, row=0, sticky="news")
92
- self._root.columnconfigure(0, weight=1)
93
- self._root.rowconfigure(0, weight=1)
94
- mainframe.columnconfigure(0, weight=1)
95
- mainframe.rowconfigure(0, weight=1)
96
-
97
- # Server serving settings.
98
-
99
- server_serving_settings = ttk.LabelFrame(mainframe, text="Serving Settings", padding=3)
100
- server_serving_settings.grid(column=0, row=0, sticky="news")
101
-
102
- # Local IP.
103
- ttk.Label(server_serving_settings, text="Local IP:", anchor=E, justify=RIGHT).grid(column=0, row=0, sticky="we")
104
- ttk.Label(server_serving_settings, text=gethostbyname(gethostname())).grid(column=1, row=0, sticky="we")
105
-
106
- # Proxy.
107
- ttk.Label(server_serving_settings, text="Use Proxy:", anchor=E, justify=RIGHT).grid(
108
- column=0, row=1, sticky="we"
109
- )
110
- ttk.Checkbutton(
111
- server_serving_settings,
112
- variable=self._use_proxy,
113
- ).grid(column=1, row=1, sticky="we")
114
-
115
- # Proxy address.
116
- ttk.Label(server_serving_settings, text="Proxy Address:", anchor=E, justify=RIGHT).grid(
117
- column=0, row=2, sticky="we"
118
- )
119
- ttk.Entry(server_serving_settings, textvariable=self._proxy_address, justify=CENTER).grid(
120
- column=1, row=2, sticky="we"
121
- )
122
-
123
- # Ignore updates.
124
- ttk.Label(server_serving_settings, text="Ignore Updates:", anchor=E, justify=RIGHT).grid(
125
- column=0, row=4, sticky="we"
126
- )
127
- ttk.Checkbutton(
128
- server_serving_settings,
129
- variable=self._ignore_updates,
130
- ).grid(column=1, row=4, sticky="we")
131
-
132
- # Debug mode.
133
- ttk.Label(server_serving_settings, text="Debug mode:", anchor=E, justify=RIGHT).grid(
134
- column=0, row=5, sticky="we"
135
- )
136
- ttk.Checkbutton(
137
- server_serving_settings,
138
- variable=self._debug,
139
- ).grid(column=1, row=5, sticky="we")
140
-
141
- # ---
142
-
143
- # Platform type.
144
- platform_type_settings = ttk.LabelFrame(mainframe, text="Platform Type", padding=3)
145
- platform_type_settings.grid(column=0, row=1, sticky="news")
146
-
147
- ttk.Radiobutton(
148
- platform_type_settings,
149
- text="Sensapex uMp-4",
150
- variable=self._type,
151
- value="ump-4",
152
- ).grid(column=0, row=0, sticky="we")
153
- ttk.Radiobutton(
154
- platform_type_settings,
155
- text="Sensapex uMp-3",
156
- variable=self._type,
157
- value="ump-3",
158
- ).grid(column=0, row=1, sticky="we")
159
- ttk.Radiobutton(
160
- platform_type_settings,
161
- text="Pathfinder MPM Control v2.8.8+",
162
- variable=self._type,
163
- value="pathfinder-mpm",
164
- ).grid(column=0, row=2, sticky="we")
165
- ttk.Radiobutton(
166
- platform_type_settings,
167
- text="New Scale M3-USB-3:1-EP",
168
- variable=self._type,
169
- value="new-scale",
170
- ).grid(column=0, row=3, sticky="we")
171
- ttk.Radiobutton(
172
- platform_type_settings,
173
- text="Fake Platform",
174
- variable=self._type,
175
- value="fake",
176
- ).grid(column=0, row=4, sticky="we")
177
-
178
- # ---
179
-
180
- # New Scale Settings.
181
- new_scale_settings = ttk.LabelFrame(mainframe, text="Pathfinder MPM Settings", padding=3)
182
- new_scale_settings.grid(column=0, row=2, sticky="news")
183
-
184
- # Port
185
- ttk.Label(new_scale_settings, text="HTTP Server Port:", anchor=E, justify=RIGHT).grid(
186
- column=0, row=1, sticky="we"
187
- )
188
- ttk.Entry(new_scale_settings, textvariable=self._mpm_port, width=5, justify=CENTER).grid(
189
- column=1, row=1, sticky="we"
190
- )
191
-
192
- # ---
193
-
194
- # Emergency Stop serial port.
195
- e_stop_settings = ttk.LabelFrame(mainframe, text="Emergency Stop Settings", padding=3)
196
- e_stop_settings.grid(column=0, row=3, sticky="news")
197
-
198
- # Serial Port
199
- ttk.Label(e_stop_settings, text="Serial Port:", anchor=E, justify=RIGHT).grid(column=0, row=1, sticky="we")
200
- ttk.Entry(e_stop_settings, textvariable=self._serial, justify=CENTER).grid(column=1, row=1, sticky="we")
201
-
202
- # Server launch button.
203
- ttk.Button(
204
- mainframe,
205
- text="Launch Server",
206
- command=self._launch_server,
207
- ).grid(column=0, row=4, columnspan=2, sticky="we")
208
-
209
- def _launch_server(self) -> None:
210
- """Close GUI and return to the server.
211
-
212
- Options are saved in fields.
213
- """
214
- self._submit = True
215
- self._root.destroy()
1
+ """Graphical User Interface for Ephys Link.
2
+
3
+ Usage:
4
+ Create a GUI instance and call `get_options()` to get the options.
5
+
6
+ ```python
7
+ GUI().get_options()
8
+ ```
9
+ """
10
+
11
+ from json import load
12
+ from os import makedirs
13
+ from os.path import exists, join
14
+ from socket import gethostbyname, gethostname
15
+ from sys import exit
16
+ from tkinter import CENTER, RIGHT, BooleanVar, E, IntVar, StringVar, Tk, ttk
17
+ from typing import final
18
+
19
+ from platformdirs import user_config_dir
20
+ from vbl_aquarium.models.ephys_link import EphysLinkOptions
21
+
22
+ from ephys_link.__about__ import __version__ as version
23
+ from ephys_link.utils.startup import get_binding_display_to_cli_name
24
+
25
+ # Define options path.
26
+ OPTIONS_DIR = join(user_config_dir(), "VBL", "Ephys Link")
27
+ OPTIONS_FILENAME = "options.json"
28
+ OPTIONS_PATH = join(OPTIONS_DIR, OPTIONS_FILENAME)
29
+
30
+
31
+ @final
32
+ class GUI:
33
+ """Graphical User Interface for Ephys Link.
34
+
35
+ Gathers options from the user and saves them to a file.
36
+ """
37
+
38
+ def __init__(self) -> None:
39
+ """Setup GUI properties."""
40
+
41
+ self._root = Tk()
42
+
43
+ # Create default options.
44
+ options = EphysLinkOptions()
45
+
46
+ # Read options.
47
+ if exists(OPTIONS_PATH):
48
+ with open(OPTIONS_PATH) as options_file:
49
+ options = EphysLinkOptions(**load(options_file)) # pyright: ignore [reportAny]
50
+
51
+ # Load options into GUI variables.
52
+ self._ignore_updates = BooleanVar(value=options.ignore_updates)
53
+ self._type = StringVar(value=options.type)
54
+ self._debug = BooleanVar(value=options.debug)
55
+ self._use_proxy = BooleanVar(value=options.use_proxy)
56
+ self._proxy_address = StringVar(value=options.proxy_address)
57
+ self._mpm_port = IntVar(value=options.mpm_port)
58
+ self._serial = StringVar(value=options.serial)
59
+
60
+ # Submit flag.
61
+ self._submit = False
62
+
63
+ def get_options(self) -> EphysLinkOptions:
64
+ """Get options from GUI.
65
+
66
+ Returns:
67
+ Options gathered from the GUI.
68
+ """
69
+
70
+ # Launch GUI.
71
+ self._build_gui()
72
+ self._root.mainloop()
73
+
74
+ # Exit if the user did not submit options.
75
+ if not self._submit:
76
+ exit(1)
77
+
78
+ # Extract options from GUI.
79
+ options = EphysLinkOptions(
80
+ ignore_updates=self._ignore_updates.get(),
81
+ type=self._type.get(),
82
+ debug=self._debug.get(),
83
+ use_proxy=self._use_proxy.get(),
84
+ proxy_address=self._proxy_address.get(),
85
+ mpm_port=self._mpm_port.get(),
86
+ serial=self._serial.get(),
87
+ )
88
+
89
+ # Save options.
90
+ makedirs(OPTIONS_DIR, exist_ok=True)
91
+ with open(OPTIONS_PATH, "w+") as options_file:
92
+ _ = options_file.write(options.model_dump_json())
93
+
94
+ # Return options
95
+ return options
96
+
97
+ def _build_gui(self) -> None:
98
+ """Build GUI."""
99
+
100
+ self._root.title(f"Ephys Link v{version}")
101
+
102
+ mainframe = ttk.Frame(self._root, padding=3)
103
+ mainframe.grid(column=0, row=0, sticky="news")
104
+ _ = self._root.columnconfigure(0, weight=1)
105
+ _ = self._root.rowconfigure(0, weight=1)
106
+ _ = mainframe.columnconfigure(0, weight=1)
107
+ _ = mainframe.rowconfigure(0, weight=1)
108
+
109
+ # Server serving settings.
110
+
111
+ server_serving_settings = ttk.LabelFrame(mainframe, text="Serving Settings", padding=3)
112
+ server_serving_settings.grid(column=0, row=0, sticky="news")
113
+
114
+ # Local IP.
115
+ ttk.Label(server_serving_settings, text="Local IP:", anchor=E, justify=RIGHT).grid(column=0, row=0, sticky="we")
116
+ ttk.Label(server_serving_settings, text=gethostbyname(gethostname())).grid(column=1, row=0, sticky="we")
117
+
118
+ # Proxy.
119
+ ttk.Label(server_serving_settings, text="Use Proxy:", anchor=E, justify=RIGHT).grid(
120
+ column=0, row=1, sticky="we"
121
+ )
122
+ ttk.Checkbutton(
123
+ server_serving_settings,
124
+ variable=self._use_proxy,
125
+ ).grid(column=1, row=1, sticky="we")
126
+
127
+ # Proxy address.
128
+ ttk.Label(server_serving_settings, text="Proxy Address:", anchor=E, justify=RIGHT).grid(
129
+ column=0, row=2, sticky="we"
130
+ )
131
+ ttk.Entry(server_serving_settings, textvariable=self._proxy_address, justify=CENTER).grid(
132
+ column=1, row=2, sticky="we"
133
+ )
134
+
135
+ # Ignore updates.
136
+ ttk.Label(server_serving_settings, text="Ignore Updates:", anchor=E, justify=RIGHT).grid(
137
+ column=0, row=4, sticky="we"
138
+ )
139
+ ttk.Checkbutton(
140
+ server_serving_settings,
141
+ variable=self._ignore_updates,
142
+ ).grid(column=1, row=4, sticky="we")
143
+
144
+ # Debug mode.
145
+ ttk.Label(server_serving_settings, text="Debug mode:", anchor=E, justify=RIGHT).grid(
146
+ column=0, row=5, sticky="we"
147
+ )
148
+ ttk.Checkbutton(
149
+ server_serving_settings,
150
+ variable=self._debug,
151
+ ).grid(column=1, row=5, sticky="we")
152
+
153
+ # ---
154
+
155
+ # Platform type.
156
+ platform_type_settings = ttk.LabelFrame(mainframe, text="Platform Type", padding=3)
157
+ platform_type_settings.grid(column=0, row=1, sticky="news")
158
+
159
+ for index, (display_name, cli_name) in enumerate(get_binding_display_to_cli_name().items()):
160
+ ttk.Radiobutton(
161
+ platform_type_settings,
162
+ text=display_name,
163
+ variable=self._type,
164
+ value=cli_name,
165
+ ).grid(column=0, row=index, sticky="we")
166
+
167
+ # ---
168
+
169
+ # New Scale Settings.
170
+ new_scale_settings = ttk.LabelFrame(mainframe, text="Pathfinder MPM Settings", padding=3)
171
+ new_scale_settings.grid(column=0, row=2, sticky="news")
172
+
173
+ # Port
174
+ ttk.Label(new_scale_settings, text="HTTP Server Port:", anchor=E, justify=RIGHT).grid(
175
+ column=0, row=1, sticky="we"
176
+ )
177
+ ttk.Entry(new_scale_settings, textvariable=self._mpm_port, width=5, justify=CENTER).grid(
178
+ column=1, row=1, sticky="we"
179
+ )
180
+
181
+ # ---
182
+
183
+ # Emergency Stop serial port.
184
+ e_stop_settings = ttk.LabelFrame(mainframe, text="Emergency Stop Settings", padding=3)
185
+ e_stop_settings.grid(column=0, row=3, sticky="news")
186
+
187
+ # Serial Port
188
+ ttk.Label(e_stop_settings, text="Serial Port:", anchor=E, justify=RIGHT).grid(column=0, row=1, sticky="we")
189
+ ttk.Entry(e_stop_settings, textvariable=self._serial, justify=CENTER).grid(column=1, row=1, sticky="we")
190
+
191
+ # Server launch button.
192
+ ttk.Button(
193
+ mainframe,
194
+ text="Launch Server",
195
+ command=self._launch_server,
196
+ ).grid(column=0, row=4, columnspan=2, sticky="we")
197
+
198
+ def _launch_server(self) -> None:
199
+ """Close GUI and return to the server.
200
+
201
+ Options are saved in fields.
202
+ """
203
+ self._submit = True
204
+ self._root.destroy()