Skip to content

Commit e5438de

Browse files
authored
Merge pull request #6 from iqnite/config-optimizaiton
Refactor config and make panel scrollable
2 parents ab87840 + 4b36c35 commit e5438de

File tree

8 files changed

+1020
-624
lines changed

8 files changed

+1020
-624
lines changed

spectrometer/CCDfiles.py

Lines changed: 136 additions & 84 deletions
Large diffs are not rendered by default.

spectrometer/CCDpanelsetup.py

Lines changed: 430 additions & 413 deletions
Large diffs are not rendered by default.

spectrometer/CCDplots.py

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,14 @@
1010
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
1111
from matplotlib.backends._backend_tk import NavigationToolbar2Tk
1212
from matplotlib.figure import Figure
13-
from spectrometer import config, calibration
13+
from spectrometer import calibration, configuration
1414
from spectrometer.spectrum_gradient import update_spectrum_background
1515

1616

1717
class BuildPlot(ttk.Frame):
18-
def __init__(self, master):
18+
def __init__(self, master, config: configuration.Config):
1919
super().__init__(master)
20+
self.config = config
2021

2122
# Configure this frame to expand
2223
self.grid_rowconfigure(0, weight=1)
@@ -93,7 +94,7 @@ def update_spectrum_background(self):
9394
"""Update spectrum background based on current settings"""
9495
try:
9596
# Get current settings
96-
current_spectroscopy_mode = config.spectroscopy_mode
97+
current_spectroscopy_mode = self.config.spectroscopy_mode
9798
current_show_colors = getattr(self, "show_colors", False)
9899

99100
# Always call the update function to handle axis changes and settings
@@ -213,7 +214,7 @@ def plot_spectrum(self, ccd_data):
213214
self.current_data = ccd_data
214215

215216
# Choose x-axis based on mode
216-
if config.spectroscopy_mode:
217+
if self.config.spectroscopy_mode:
217218
x_values = calibration.default_calibration.apply(np.arange(len(ccd_data)))
218219
x_label = "Wavelength (nm)"
219220
else:
@@ -278,7 +279,7 @@ def add_marker(self, x_pos):
278279

279280
# Determine color and elements based on element matching (if enabled and in spectroscopy mode)
280281
element_matches = []
281-
if config.spectroscopy_mode:
282+
if self.config.spectroscopy_mode:
282283
if self.element_matching_enabled:
283284
color, element_matches = self._get_marker_color_and_elements(x_pos)
284285
else:
@@ -293,7 +294,7 @@ def add_marker(self, x_pos):
293294
)
294295

295296
# Determine label based on spectroscopy mode (without units)
296-
if config.spectroscopy_mode:
297+
if self.config.spectroscopy_mode:
297298
label_text = f"{x_pos:.2f}"
298299
else:
299300
label_text = f"{int(x_pos)}"
@@ -469,7 +470,7 @@ def _get_marker_color_and_elements(self, wavelength):
469470
470471
Returns: (color, list of (element_name, match_percentage) sorted by percentage desc)
471472
"""
472-
if not self.emission_lines or not config.spectroscopy_mode:
473+
if not self.emission_lines or not self.config.spectroscopy_mode:
473474
return ("red", [])
474475

475476
# Find all emission lines and calculate match percentages
@@ -480,8 +481,8 @@ def _get_marker_color_and_elements(self, wavelength):
480481

481482
# Calculate match percentage based on distance
482483
# Use configurable thresholds from config
483-
green_threshold = config.green_tolerance_nm
484-
yellow_threshold = config.yellow_tolerance_nm
484+
green_threshold = self.config.green_tolerance_nm
485+
yellow_threshold = self.config.yellow_tolerance_nm
485486

486487
if distance <= green_threshold:
487488
# Within green tolerance: 90-100% match
@@ -546,7 +547,7 @@ def update_marker_colors(self, enabled):
546547

547548
# Calculate new color and elements
548549
element_text_obj = None
549-
if config.spectroscopy_mode:
550+
if self.config.spectroscopy_mode:
550551
if enabled:
551552
color, element_matches = self._get_marker_color_and_elements(x_pos)
552553

@@ -633,7 +634,7 @@ def save_spectrum_image(self, *_):
633634

634635
try:
635636
# Check if we're in spectroscopy mode
636-
if not config.spectroscopy_mode:
637+
if not self.config.spectroscopy_mode:
637638
messagebox.showinfo(
638639
"Spectroscopy Mode Required",
639640
"Please enable Spectroscopy Mode to export spectrum images.",

spectrometer/CCDserial.py

Lines changed: 52 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929
import serial
3030
import numpy as np
3131

32-
from spectrometer import config
32+
from spectrometer.configuration import Config
3333
import threading
3434
import tkinter as ttk
3535
import time
@@ -42,21 +42,23 @@
4242
# byte[7-10]: The 4 bytes constituting the 32-bit int holding the ICG-period
4343
# byte[11]: Continuous flag: 0 equals one acquisition, 1 equals continuous mode
4444
# byte[12]: The number of integrations to average
45-
def rxtx(panel, SerQueue, progress_var):
45+
def rxtx(panel, SerQueue, progress_var, config: Config):
4646
threadser = None
47-
if config.AVGn[0] == 0:
47+
if config.avg_n[0] == 0:
4848
threadser = threading.Thread(
49-
target=rxtxoncethread, args=(panel, SerQueue, progress_var), daemon=True
49+
target=rxtxoncethread,
50+
args=(panel, SerQueue, progress_var, config),
51+
daemon=True,
5052
)
51-
elif config.AVGn[0] == 1:
53+
elif config.avg_n[0] == 1:
5254
threadser = threading.Thread(
53-
target=rxtxcontthread, args=(panel, progress_var), daemon=True
55+
target=rxtxcontthread, args=(panel, progress_var, config), daemon=True
5456
)
5557
if threadser is not None:
5658
threadser.start()
5759

5860

59-
def rxtxoncethread(panel, SerQueue, progress_var):
61+
def rxtxoncethread(panel, SerQueue, progress_var, config: Config):
6062
# open serial port
6163
try:
6264
ser = serial.Serial(config.port, config.baudrate)
@@ -69,7 +71,7 @@ def rxtxoncethread(panel, SerQueue, progress_var):
6971
# start the progressbar
7072
panel.progress.config(mode="determinate")
7173
threadprogress = threading.Thread(
72-
target=progressthread, args=(progress_var,), daemon=True
74+
target=progressthread, args=(progress_var, config), daemon=True
7375
)
7476
threadprogress.start()
7577

@@ -81,7 +83,7 @@ def rxtxoncethread(panel, SerQueue, progress_var):
8183

8284
# Determine hardware vs software averaging
8385
# Firmware supports max 15 averages, so for >15 we need software averaging
84-
requested_avg = config.AVGn[1]
86+
requested_avg = config.avg_n[1]
8587
if requested_avg <= 15:
8688
# Use hardware averaging only
8789
hardware_avg = requested_avg
@@ -99,16 +101,16 @@ def rxtxoncethread(panel, SerQueue, progress_var):
99101
config.txfull[0] = 69
100102
config.txfull[1] = 82
101103
# split 32-bit integers to be sent into 8-bit data
102-
config.txfull[2] = (config.SHperiod >> 24) & 0xFF
103-
config.txfull[3] = (config.SHperiod >> 16) & 0xFF
104-
config.txfull[4] = (config.SHperiod >> 8) & 0xFF
105-
config.txfull[5] = config.SHperiod & 0xFF
106-
config.txfull[6] = (config.ICGperiod >> 24) & 0xFF
107-
config.txfull[7] = (config.ICGperiod >> 16) & 0xFF
108-
config.txfull[8] = (config.ICGperiod >> 8) & 0xFF
109-
config.txfull[9] = config.ICGperiod & 0xFF
104+
config.txfull[2] = (config.sh_period >> 24) & 0xFF
105+
config.txfull[3] = (config.sh_period >> 16) & 0xFF
106+
config.txfull[4] = (config.sh_period >> 8) & 0xFF
107+
config.txfull[5] = config.sh_period & 0xFF
108+
config.txfull[6] = (config.icg_period >> 24) & 0xFF
109+
config.txfull[7] = (config.icg_period >> 16) & 0xFF
110+
config.txfull[8] = (config.icg_period >> 8) & 0xFF
111+
config.txfull[9] = config.icg_period & 0xFF
110112
# averages to perfom (send hardware average count)
111-
config.txfull[10] = config.AVGn[0]
113+
config.txfull[10] = config.avg_n[0]
112114
config.txfull[11] = hardware_avg
113115

114116
# Perform software averaging by collecting multiple times
@@ -120,7 +122,7 @@ def rxtxoncethread(panel, SerQueue, progress_var):
120122
ser.write(config.txfull)
121123

122124
# wait for the firmware to return data
123-
config.rxData8 = ser.read(7388)
125+
config.rxData8 = np.frombuffer(ser.read(7388), dtype=np.uint8)
124126

125127
# combine received bytes into 16-bit data
126128
for rxi in range(3694):
@@ -134,19 +136,21 @@ def rxtxoncethread(panel, SerQueue, progress_var):
134136
ser.close()
135137

136138
# enable all buttons
137-
panelwakeup(panel)
139+
panelwakeup(panel, config)
138140

139141
if config.stopsignal == 0:
140142
# If we did software averaging, compute the average
141143
if software_iterations > 1:
142144
for rxi in range(3694):
143-
config.rxData16[rxi] = np.uint16(np.round(accumulated_data[rxi] / software_iterations))
145+
config.rxData16[rxi] = np.uint16(
146+
np.round(accumulated_data[rxi] / software_iterations)
147+
)
144148

145149
# plot the new data
146150
panel.bupdate.invoke()
147151
# hold values for saving data to file as the SHperiod and ICGperiod may be updated after acquisition
148-
config.SHsent = config.SHperiod
149-
config.ICGsent = config.ICGperiod
152+
config.sh_sent = config.sh_period
153+
config.icg_sent = config.icg_period
150154

151155
SerQueue.queue.clear()
152156

@@ -157,7 +161,7 @@ def rxtxoncethread(panel, SerQueue, progress_var):
157161
)
158162

159163

160-
def rxtxcontthread(panel, progress_var):
164+
def rxtxcontthread(panel, progress_var, config: Config):
161165
# open serial port
162166
try:
163167
ser = serial.Serial(config.port, config.baudrate)
@@ -181,25 +185,25 @@ def rxtxcontthread(panel, progress_var):
181185
config.txfull[0] = 69
182186
config.txfull[1] = 82
183187
# split 32-bit integers to be sent into 8-bit data
184-
config.txfull[2] = (config.SHperiod >> 24) & 0xFF
185-
config.txfull[3] = (config.SHperiod >> 16) & 0xFF
186-
config.txfull[4] = (config.SHperiod >> 8) & 0xFF
187-
config.txfull[5] = config.SHperiod & 0xFF
188-
config.txfull[6] = (config.ICGperiod >> 24) & 0xFF
189-
config.txfull[7] = (config.ICGperiod >> 16) & 0xFF
190-
config.txfull[8] = (config.ICGperiod >> 8) & 0xFF
191-
config.txfull[9] = config.ICGperiod & 0xFF
188+
config.txfull[2] = (config.sh_period >> 24) & 0xFF
189+
config.txfull[3] = (config.sh_period >> 16) & 0xFF
190+
config.txfull[4] = (config.sh_period >> 8) & 0xFF
191+
config.txfull[5] = config.sh_period & 0xFF
192+
config.txfull[6] = (config.icg_period >> 24) & 0xFF
193+
config.txfull[7] = (config.icg_period >> 16) & 0xFF
194+
config.txfull[8] = (config.icg_period >> 8) & 0xFF
195+
config.txfull[9] = config.icg_period & 0xFF
192196
# averages to perfom
193-
config.txfull[10] = config.AVGn[0]
194-
config.txfull[11] = config.AVGn[1]
197+
config.txfull[10] = config.avg_n[0]
198+
config.txfull[11] = config.avg_n[1]
195199

196200
# transmit everything at once (the USB-firmware does not work if all bytes are not transmittet in one go)
197201
ser.write(config.txfull)
198202

199203
# loop to acquire and plot data continuously
200204
while config.stopsignal == 0:
201205
# wait for the firmware to return data
202-
config.rxData8 = ser.read(7388)
206+
config.rxData8 = np.frombuffer(ser.read(7388), dtype=np.uint8)
203207

204208
if config.stopsignal == 0:
205209
# combine received bytes into 16-bit data
@@ -211,8 +215,8 @@ def rxtxcontthread(panel, progress_var):
211215
# plot the new data
212216
panel.bupdate.invoke()
213217
# hold values for saving data to file
214-
config.SHsent = config.SHperiod
215-
config.ICGsent = config.ICGperiod
218+
config.sh_sent = config.sh_period
219+
config.icg_sent = config.icg_period
216220

217221
# resend settings with continuous transmission disabled to avoid flooding of the serial port
218222
config.txfull[10] = 0
@@ -224,7 +228,7 @@ def rxtxcontthread(panel, progress_var):
224228

225229
# close serial port
226230
ser.close()
227-
panelwakeup(panel)
231+
panelwakeup(panel, config)
228232
panel.progress.stop()
229233

230234
except serial.SerialException:
@@ -234,11 +238,11 @@ def rxtxcontthread(panel, progress_var):
234238
)
235239

236240

237-
def progressthread(progress_var):
241+
def progressthread(progress_var, config: Config):
238242
progress_var.set(0)
239-
243+
240244
# Calculate total time considering software averaging
241-
requested_avg = config.AVGn[1]
245+
requested_avg = config.avg_n[1]
242246
if requested_avg <= 15:
243247
# Hardware averaging only
244248
hardware_avg = requested_avg
@@ -247,25 +251,25 @@ def progressthread(progress_var):
247251
# Software averaging with multiple collections
248252
hardware_avg = 15
249253
software_iterations = int(np.ceil(requested_avg / 15.0))
250-
254+
251255
# Total time is: ICGperiod * hardware_avg * software_iterations
252-
total_time = config.ICGperiod * hardware_avg * software_iterations / config.MCLK
253-
256+
total_time = config.icg_period * hardware_avg * software_iterations / config.mclk
257+
254258
# Add overhead for serial communication and data processing per iteration
255259
# Estimate ~0.5 seconds per iteration for serial read and processing
256260
serial_overhead = software_iterations * 0.5
257261
total_time += serial_overhead
258-
262+
259263
for i in range(1, 11):
260264
progress_var.set(i)
261265
# wait 1/10th of the total acquisition time before adding to progress bar
262266
time.sleep(total_time / 10)
263267

264268

265-
def rxtxcancel(SerQueue):
269+
def rxtxcancel(SerQueue, config: Config):
266270
config.stopsignal = 1
267271
# Are we stopping one very long measurement, or the continuous real-time view?
268-
if config.AVGn[0] == 0:
272+
if config.avg_n[0] == 0:
269273
ser = SerQueue.get()
270274
ser.cancel_read()
271275

@@ -289,7 +293,7 @@ def panelsleep(panel):
289293
pass
290294

291295

292-
def panelwakeup(panel):
296+
def panelwakeup(panel, config: Config):
293297
panel.bstop.config(state=ttk.DISABLED)
294298
panel.bopen.config(state=ttk.NORMAL)
295299
panel.bsave.config(state=ttk.NORMAL)

spectrometer/config.py

Lines changed: 0 additions & 42 deletions
This file was deleted.

0 commit comments

Comments
 (0)