Repository navigation
Replace SpectraViewer save dialog with an in-figure filename TextBox - #84
Merged
Merged
Conversation
Three problems converged in clickSave before this commit: 1. Non-reentrant threading.Lock held by both animate() and clickSave() deadlocked whenever matplotlib's FuncAnimation timer fired while the macOS save dialog was open. 2. matplotlib 3.10 changed the signature of the private C function backend_macosx._macosx.choose_save_file from 2 args to 3. clickSave's previous fallback (bare except: -> Tk) hid this as a TypeError that matplotlib silently swallowed in its event handler. Result: "click Save, nothing happens". 3. Replacing the macOS path with Tk's filedialog.asksaveasfilename triggered SIGSEGV. macOS's main thread can only host one NSRunLoop, and Tk's modal dialog tries to start a second one alongside matplotlib's own. All three are mixing-GUI-run-loops problems. Rather than keep fighting it, the save path now uses matplotlib's own TextBox widget (already used elsewhere in this viewer for integration time) to get the filename from the user. Changes in hardwarelibrary/spectrometers/viewer.py: - Add a `filenameBox = TextBox(..., initial='spectrum.csv')` to the control row; clickSave reads its `.text` directly. - Remove the threading.Lock + matplotlib.backends import + the askForSavePath helper. clickSave is now a straightforward stop-animation / write-CSV / restart-animation block. - Stop animation around saveSpectrum() with try/finally so the animation resumes even if writing the file raises (matches the intent of the original docstring, which the old code didn't actually honor). - Re-layout the control bar: shrink button heights, shorten the integration-time label to "ms ", widen the filename TextBox to ~0.30 width, and squeeze ms/Save/Quit to the right edge. Verified by writing a CSV through the live viewer using a DebugSpectro device (no run-loop conflict, no segfault, file written to disk). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
dccote
force-pushed
the
spectrometer-save-no-lock
branch
from
May 19, 2026 00:08
97304ed to
8672c73
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Replaces `SpectraViewer.clickSave`'s native file-dialog with an in-figure `TextBox` widget. The user types the path inline; Save reads it directly. No platform file dialog is involved.
This fixes all three of the compounding bugs that surfaced while debugging the original "Save locks up very often" report:
Non-reentrant lock deadlock. `threading.Lock` was held by both `animate()` and `clickSave()`. Whenever matplotlib's animation timer fired during the save dialog, the timer callback ran on the same main thread holding the lock and deadlocked.
matplotlib 3.10 broke the macOS C dialog. `backend_macosx._macosx.choose_save_file` changed signature from 2 args to 3 between matplotlib versions. The old code's bare `except:` had hidden the resulting `TypeError` so the user saw "click Save, nothing happens".
Tk + macOS NSRunLoop = SIGSEGV. Falling back to `tkinter.filedialog.asksaveasfilename` segfaulted (exit 139). macOS only allows one NSRunLoop owner per main thread; matplotlib's `macosx` backend already owns it, and Tk's modal dialog tries to start a competing loop.
All three are run-loop-mixing failures. The fix sidesteps them by not invoking any second GUI toolkit during save.
Changes (`hardwarelibrary/spectrometers/viewer.py`)
Net: +54 / −59 lines in one file.
Test plan
Why a TextBox instead of switching backends
The other paths considered:
🤖 Generated with Claude Code