GUI Module (songs.gui)#
Full class and method reference for the Tkinter front end, auto-generated from docstrings. For a task-oriented walkthrough of the interface itself, see GUI User Guide.
SONGS GUI
Compact Tkinter-based GUI to interactively configure and run the
SONGS generator. Provides a 4-column card layout of parameter
frames (Initialisation, Central Galaxy, Satellite, Diffuse Features),
crisp LaTeX-rendered labels, convenience sliders, and utility buttons
(Generate, Slice, Moments, Spectrum, Save, New). Plotting and file I/O
are intentionally kept out of the generator core; the GUI imports
top-level visualisation helpers (moment0, moment1, spectrum,
slice_view) to display results.
Design notes#
- Lightweight: the GUI focuses on inspection and quick interactive
experimentation, not production batch runs.
- Threading: generation runs in a background thread so the UI remains
responsive; generated figures are produced by the visualise helpers.
- Cleanup: LaTeX labels are rendered to temporary PNG files (via
matplotlib) and tracked in
_MATH_TEMPFILESfor removal when the application exits.
Usage#
Run the module as a script to display the GUI:
python -m songs.gui
Or instantiate SONGSGUI and call mainloop(). The GUI
expects the package to be importable (it will try a fallback path insertion
when executed as a script).
- class songs.gui.LogWindow(master)[source]#
Bases:
ToplevelTop-level log window that captures and displays stdout/stderr.
LogWindowcreates a simple resizable Toplevel containing a TkTextwidget and installsTextRedirectorinstances onsys.stdoutandsys.stderrso that all subsequentprintoutput and uncaught exception tracebacks are visible in the GUI. The window restores the original streams when closed.Behaviour#
- Creating an instance replaces
sys.stdoutandsys.stderrin the running interpreter until the window is closed (
on_close).
- Creating an instance replaces
- The window configures a separate text tag for
stderrso error messages are coloured differently.
- The window configures a separate text tag for
Example
>>> log = LogWindow(root) >>> log.deiconify() # show the window
- class songs.gui.SONGSGUI(theme: str = 'light')[source]#
Bases:
TkMain GUI application for interactively configuring and running SONGS simulations.
This class implements a compact, self-contained Tk application, launched with
python -m songs.gui, that exposes the most commonly-used parameters of the generator through a 4-column dark-themed (or light-themed) card layout, with the SONGS banner running down the left side:Initialisation — grid size, number of spectral channels, number of galaxies, random seed, output directory.
Central Galaxy — Sérsic index, effective radius, scale height, central flux density, inclination, position angle.
Satellite — satellite offset, systemic velocity offset, beam parameters (bmin, bmaj, BPA).
Diffuse Features — sliders/entries mapping onto
DEFAULT_DIFFUSE_PARAMS(halo, bridge and tail amplitudes, tail velocity gradient and decay scale, master enabled toggle).
Controls include numeric sliders, textual inputs and convenience buttons that invoke high-level visualisation helpers (
moment0,moment1,spectrum) or persist generated results to disk. Seedocs/source/gui.rstfor a full description of the layout and workflow.Key behaviour#
- The generator is constructed from the current UI values and stored
on
self.generator. CallingGenerateruns the generator in a background daemon thread so the UI remains responsive; generated results become available viaself.generator.results.
- Visualisation buttons call into functions defined in
songs.visualisewhich create Matplotlib figures; these functions are intentionally separate from the generator core so the GUI remains a thin orchestration layer.
- Temporary files created by
latex_label()are tracked in the module-level
_MATH_TEMPFILESlist and cleaned up when the GUI is closed via_on_close.
- Temporary files created by
Threading and shutdown#
- Generation and save operations spawn background daemon threads. The
UI schedules finalisation callbacks back on the main thread using
self.after(...)when worker threads complete.
- Closing the main window triggers a cleanup of temporary files and
forces process termination to avoid orphaned interpreters. If you prefer a softer shutdown that joins worker threads, modify
_on_closeaccordingly.
Usage example#
Run the GUI as a script:
python -m songs.gui
Or instantiate from Python:
from songs.gui import SONGSGUI app = SONGSGUI() app.mainloop()
- create_generator()[source]#
Instantiate a
SONGSobject from current UI values.The method calls
_collect_parameters()to assemble a parameter dictionary and then constructs a single-cube generator instance with sensible defaults for fields not exposed directly in the GUI. After construction the per-galaxy attributes on the generator are filled from the collected parameters so the generator is ready to run.
- generate()[source]#
Handle a click on the Generate button (single-cube mode).
Builds a fresh
SONGSgenerator from the current UI values (viacreate_generator()), disables the theme and result buttons for the duration of the run, and launches_run_generate()on a background daemon thread so the UI stays responsive._poll_generation_done()is scheduled on the main thread to detect completion, publish the results, and re-enable the buttons.
- generate_dataset()[source]#
Kick off batch generation for Large-Dataset Mode: samples fresh parameters per cube, generates it, optionally adds correlated beam-convolved noise, and writes clean/noisy HDF5 files (with the full per-cube parameter manifest as a JSON header attribute) plus one dataset-level pickle summarising every cube. Runs in a background thread; the GUI only reads/writes Tk state before the thread starts and via
self.after(0, ...)afterwards.
- load_cube()[source]#
Open a SONGS HDF5 cube for viewing only (Slice/Analysis), without running the generator. Populates every slider from the file’s
parameters_jsonheader and locks the UI read-only until Reset is pressed. If the file has both a clean and a noisy version of the cube (see _save_cube_hdf5), both are loaded and the Slice/Analysis viewers get the same Clean/Noisy toggle used for live generation — no more up-front “which one?” prompt.
- make_dual_slider(parent, segs, var, var_min, var_max, from_, to, resolution=0.01, fmt='{:.2f}', integer=False)[source]#
A single card row that shows a classic make_slider() (single value,
var) in single-cube mode, or a make_range_slider() (var_min/var_max) in Large-Dataset Mode — swapped in place whenever the mode toggles (see self._dual_sliders, refreshed by _apply_large_dataset_mode). Every parameter in Central Galaxy / Satellite / Diffuse Features uses this so the same card works in both modes.
- make_range_slider(parent, var_lo, var_hi, from_, to, resolution=0.01, fmt='{:.2f}', integer=False)[source]#
Single-row dual-handle range slider: an editable entry for each bound flanking a draggable two-handle track, used for min/max parameter ranges in Large-Dataset Mode.
lo <= hiis enforced by construction (dragging/typing one handle past the other clamps it there).
- make_slider(parent, label, var, from_, to, resolution=0.01, fmt='{:.2f}', integer=False)[source]#
Create a labelled slider widget with snapping and a value label.
- reset_instance()[source]#
Reset the GUI to a fresh state and disable visualisation/save.
This clears the in-memory
self.generatorreference so that the next generate action will create a new instance from current UI values. Buttons that depend on generated results are disabled. If we were viewing a cube loaded viaload_cube(), this also re-enables every parameter card that load dimmed, restores every slider/toggle to the app’s hardcoded defaults (undoing_apply_loaded_manifest), and restores Generate to its normal clickable state. If a Large-Dataset Mode batch run is currently in progress, this also requests it stop (same as clicking Stop) — the background worker unwinds cooperatively at its next safe point.
- save_sim()[source]#
Generate (if needed) and save the sim tuple (cube, params).
This runs generation in a background thread and then opens a Save-As dialog on the main thread to let the user choose where to store the result. We support .npz (numpy savez) and .pkl (pickle) formats; complex parameter dicts fall back to pickle.
- show_analysis()[source]#
Open the combined Analysis viewer (moments + spectrum + source checkboxes) — or, if one is already open and still current, bring it to front instead of stacking a second window.
- show_logs()[source]#
Handle a click on the Logs button: raise the stdout/stderr log window.
Delegates to
_show_log_window(), which deiconifies the window (it starts withdrawn at startup, so a barelift()would leave it invisible) and applies the themed title bar.
- show_slice()[source]#
Open the SONGS SliceViewer for the first generated cube — or, if one is already open and still current, bring it to front instead of stacking a second window.
- stop_generation()[source]#
Request cancellation of whatever generation is currently running (single-cube or Large-Dataset Mode batch). Cooperative — the background worker checks
self._stop_requestedat its next safe point and unwinds itself; this just raises the flag and gives immediate feedback (disabling the Stop button so a second click can’t double-fire).
- class songs.gui.TextRedirector(widget, tag='stdout')[source]#
Bases:
objectRedirect writes into a Tk
Textwidget behaving like a stream.Use this helper to capture and display program output inside the GUI (for example, to show progress logs, exceptions, or print() output).
TextRedirectorimplements a minimal stream interface (writeandflush) so it can be assigned directly tosys.stdoutorsys.stderr; written text is inserted into the provided Tk Text widget and scrolled to the end so the latest output is visible.Threading note#
The class itself is not thread-safe: writes coming from background threads should be marshalled to the Tk mainloop (e.g. via
widget.after(...)) if there is a risk of concurrent access.
- param widget:
The Tk Text widget where text will be appended.
- type widget:
tk.Text
- param tag:
Optional text tag name to apply to inserted text (default
'stdout').- type tag:
str, optional
Example
Redirect stdout into a Text widget:
txt = tk.Text(root) txt.pack() sys.stdout = TextRedirector(txt, tag='log')
- songs.gui.main()[source]#
Entry point for
python -m songs.gui.Parses
--dark/--lightcommand-line flags, applies the macOS HiDPI fix (must run before the Tk root window is created), then instantiates and runsSONGSGUI.
- songs.gui.param_frame(parent, padding=8, border_color='#797979', bg='#303030', width=None, height=80, do_pack=True)[source]#
Create a framed parameter panel used throughout the GUI.
- songs.gui.rich_label(parent, segments, bg=None, fg='white')[source]#
Render a symbol with superscript/subscript on a tk.Canvas.
Uses exact pixel placement so subscript descenders are never clipped.
- Parameters:
parent (tk.Widget)
segments (list of (str, str) where the second element is one of:) –
'n'— normal baseline's'— subscript (small, lowered)'p'— superscript (small, raised)bg (str or None Background colour; defaults to parent's background.)
fg (str Foreground (text) colour.)
- Return type:
tk.Canvas Sized exactly to the rendered content.