Blackchirp 2.0.0
Blackchirp 2.0.0 is a major release that replaces the qmake build with CMake and ships official binary packages, replaces compile-time hardware selection with a runtime configuration model, introduces Python hardware drivers as a first-class implementation type, rebuilds the acquisition pipeline around a lock-free ring buffer, and overhauls logging, configuration, and the on-disk hardware identifier scheme. A v1.x user upgrading to 2.0 should also read the migration guide, which walks through the upgrade actions for each user-visible change below.
Highlights
Replaced the qmake build with CMake and added official binary packages for Linux, Windows, and macOS, so most users no longer need to build from source. See Installation.
Replaced compile-time hardware selection with a runtime configuration model: a single binary supports any combination of compatible hardware, organized into profiles, loadouts, and FTMW presets selectable from the Hardware menu. See Hardware and Library Configuration.
Added Python hardware drivers as a first-class implementation type alongside the C++ drivers, with hot reload, custom protocol support, and per-type capability declarations. See Python Hardware.
Rebuilt the FTMW acquisition pipeline around a single-producer single-consumer ring buffer with parallel batched parse and accumulate, raising sustained shot rates and reducing dropped frames under load. See Viewing FTMW Data.
Consolidated logging through a thread-safe
LogHandlerand replacedqDebug()everywhere with thebcLog/bcWarn/bcError/bcDebugandhwLog/hwWarn/hwError/hwDebugfree-function families; a runtime debug-logging toggle in the new Application Configuration dialog writes adebug_YYYYMM.csvfile when enabled. See Application Log and Application Configuration.Added an in-process crash handler that captures POSIX signals (Linux, macOS) and Windows unhandled exceptions to a diagnostic report under
<savePath>/log/crashes/, with a startup notification when an earlier run crashed. Release builds keep debug info so the captured frames resolve to source lines viaaddr2line/atos/ WinDbg. See Crash Reports.Overhauled the documentation: refreshed the User Guide end to end against the 2.0 feature set, added the new Developer Guide for contributors, and substantially expanded the C++ API reference to cover the hardware, experiment, persistence, and orchestration classes.
Refreshed the companion
blackchirpPython package against the v2 on-disk schema, added LIF read and processing support (BCLIF,BCLifTrace), extendedBCFTMWwith a differential-FID API and configurable axis units, hardened the reader against schema drift across v1 and v2 fixtures, and restructured the Sphinx pages into a per-class layout. Tagged on PyPI as0.1.0rc1. See Python Module.
Build and distribution
Replaced the qmake build with CMake.
config.priis no longer used; build options are configured through CMake cache variables. See Installation.Added official binary packages for Linux, Windows, and macOS, with bundled Qt redistributables on Windows and macOS. See Installation.
Added cross-platform CPack packaging assets and a GitHub Actions release workflow that produces release artifacts for every supported platform.
Added a user-configurable hardware-selection system at configure time (
BC_ALLHARDWAREand per-driver toggles) so packagers can produce restricted builds when needed. See Installation.Declared Eigen3 as an explicit CMake dependency.
Added a CMake documentation build (Sphinx + Doxygen) with dual-Doxyfile support for ReadTheDocs.
Replaced the static
virtualdata.qrcresource with a dynamic FID simulation generator, so the Virtual digitizer produces synthetic data without bundling sample CSVs. See First Run.
Hardware configuration
Added the runtime hardware configuration model with profiles, loadouts, and FTMW presets. Hardware is enabled and configured from the Runtime Hardware Configuration dialog without recompilation. See Hardware Profiles, Loadouts, and FTMW Presets.
Added a first-run hardware onboarding flow that walks a new user through profile creation. See First Run.
Added the Hardware Loadouts submenu and a loadout selector in the runtime hardware configuration dialog. See Hardware Menu.
Added the FTMW preset bar with full create, copy, save-as, and delete operations. See FTMW Presets.
Added the consolidated FTMW Configuration menu entry and
FtmwConfigDialog, replacing the v1.x scattered FTMW pages. See FTMW Configuration.Added the unified Application Configuration dialog (font, save path, runtime LIF toggle, debug-logging toggle), replacing the per-setting menu entries from v1.x. See Application Configuration.
Added a
VendorLibrarystaging system and a Library Configuration interface for managing externally-supplied drivers, with platform-specific installation guidance. See Library Status and Installation.Added the hardware settings registry: per-device settings are declared once and rendered into the per-device dialog by the
HwSettingsWidgetwith priority-grouped layout. All hardware classes (flow controllers, pressure controllers, temperature controllers, IO boards, GPIB controllers, LIF lasers and digitizers, FTMW digitizers, clocks, chirp sources, and pulse generators) were migrated onto the registry. See Hardware Dialog.Added per-object hardware threading configuration to the hardware profile. See Hardware Profiles.
Added a “Direct Control” hardware concept for hardware operated outside an experiment. See Hardware and Library Configuration.
Hardware drivers
Added Python hardware drivers backed by a
QProcess/ JSON-IPC bridge, with hot reload from the per-device dialog and per-type trampolines for AWGs, flow controllers, IO boards, clocks, pressure controllers, temperature controllers, FTMW digitizers, LIF digitizers, pulse generators, GPIB controllers, and LIF lasers. See Python Hardware.Python drivers expose RS232, TCP, GPIB, and Custom protocols. See Per-Type Capabilities.
The Python hardware combo box prepopulates from class names scanned out of available scripts. See Selecting a Python Driver.
Added runtime communication-protocol selection per hardware object via the per-device dialog, with protocol-specific widgets backed by group-based settings storage. See Hardware Dialog.
Modernized the GPIB controller architecture so multiple GPIB controllers (mixed LAN and RS232) cohabitate in one installation. See Hardware Details.
Added Test Connection and Communication Settings shortcuts to the per-device dialog. See Hardware Dialog.
Replaced the four fixed AWG protection/gate spinboxes with a generalized marker system: arbitrary
MarkerChannel/MarkerRoledefinitions are entered through a marker table on the chirp configuration tab. See Markers Tab on the chirp setup page.Added the LabJack vendor-library wrapper with platform- specific backends (Linux/macOS exodriver, Windows UD), so LabJack support no longer requires the exodriver at compile time. See Library Status and Installation.
Added the Spectrum vendor-library wrapper with dynamic loading for both Spectrum digitizer families. See Library Status.
Acquisition and data flow
Replaced the per-shot Qt signal waveform path with a single-producer single-consumer ring buffer (
WaveformBuffer) and a worker-thread parse/accumulate stage. See Viewing FTMW Data.Added backpressure-triggered pre-accumulation in
FtmwDigitizerso the worker thread keeps up under bursty load. See Viewing FTMW Data.Added parallel batched parse and accumulate in
AcquisitionManager. See Viewing FTMW Data.Consolidated the FTMW experiment-setup pages into
FtmwConfigWidget. See Experiment Setup.Extracted the LO scan and DR scan controls into reusable widgets and incorporated them into the experiment-wizard Type page. See FTMW Experiment Setup.
The number-of-chirps spinbox is now enabled unconditionally; a warning is emitted when the active digitizer does not support multi-record acquisition. See Digitizer Setup.
User interface
Added a Help menu with About dialog, library information, and links to online resources. See User Interface Overview.
Added the FTMW preset submenu under the Hardware menu. See Hardware Menu.
Reworked the experiment-info panel and wired
HwStatusBoxconfigure actions so each status box opens the device dialog directly. See User Interface Overview.Polished the left-side status panel layout and shortened hardware status box titles. See User Interface Overview.
Added a Fixed step mode and full-precision handling to the
ScientificSpinBox. See User Interface Overview.Added a Save-As workflow on the FTMW preset bar that copies the current configuration into a new preset, with drift-detection on Save. See Hardware Menu.
Updated the Peak Find Widget icon. See Viewing FTMW Data.
Added an Appearance button to the Peak Find toolbar that opens the FT peak-marker styling editor directly, without hunting for the curve in the main-plot right-click menu. See Viewing FTMW Data.
Added a Peak Find display filter: a toggleable 2x2 grid filters the peak table by frequency and intensity range, plus a separate “In view” toggle that limits the table to peaks within the main FT plot’s visible range. These filters affect only the displayed table, not the search bounds or the peaks drawn on the plot. See Viewing FTMW Data.
Added peak navigation to the Peak Find panel: double-click a row to center the main FT plot on that peak, or use the row’s “Center on” context menu to frame any FT plot. With the table focused, Enter re-centers the current peak, Up/Down step through the visible rows, and Left/Right step to the next lower/higher frequency peak across the full peak list (regardless of filtering or sort order), centering the main plot on each. The frequency window half-width is configurable in the Peak Finding Options dialog. See Viewing FTMW Data.
The Peak Find search parameters (frequency range, SNR, window size, polynomial order, and navigation half-width) are now remembered per experiment, stored in a
peakfind.csvfile and falling back to the application-wide defaults when none has been saved, mirroring the FID processing-settings behavior. See Viewing FTMW Data.Added a selectable column delimiter for curve XY exports: a drop-down beside the right-click
Export XYaction chooses semicolon, comma, tab, or aligned whitespace. The choice is persisted application-wide and shared between Blackchirp and the viewer. See Plot Controls.Relaxed the experiment-setup dialog minimum size. See Experiment Setup.
Streamlined the overlay creation and configuration dialog: flattened the nested group boxes into aligned settings tables and moved the validity and progress indicators into the dialog button bar. See Overlays.
Logging and diagnostics
Redesigned
LogHandleras a thread-safe global singleton with aQAnyStringViewAPI. See Application Log.Added
bcLog/bcWarn/bcError/bcDebugandhwLog/hwWarn/hwError/hwDebugfree functions and migrated every call site in the source tree offlogMessagesignals andqDebug(). See Application Log.Added a runtime debug-logging toggle in the Application Configuration dialog; when enabled, debug-level output is written to a
debug_YYYYMM.csvfile alongside the standard log. See Application Configuration.Successful connection-test events are highlighted in the Log tab so they stand out from informational chatter. See Application Log.
Added an in-process crash handler. POSIX installs
sigactionhandlers (SIGSEGV/SIGABRT/SIGFPE/SIGILL/SIGBUS) on asigaltstackand writes a text crash log via rawwrite(2)with frames resolved throughdladdrtomodule(+0xoffset) [0xpc]lines. Windows installsSetUnhandledExceptionFilterplus the C-runtime auxiliaries and emits a minidump (MiniDumpWriteDump) alongside a matching text sidecar so triage tooling sees the same header on both platforms. Crash artifacts land under<savePath>/log/crashes/and carry the build identity (git SHA) so they can be resolved against an unstripped binary. See Crash Reports and Crash Handling and Triage (68449b0b).Added a startup notification dialog when prior crash reports are present. The most recent acknowledged timestamp is persisted under the dialog’s settings group, so a dismissed report does not re-prompt unless a still-newer crash arrives. See Crash Reports (68449b0b).
Release builds now keep debug info (
-g//Zi) so the crash-handler stacktraces resolve against the unstripped binary. Stripping continues to happen at install time incmake/Packaging.cmake(68449b0b).
File formats and data storage
Introduced QSettings versioning: each major version stores its configuration under its own QSettings namespace (
Blackchirp2,Blackchirp3, …), so v1.x and v2.x do not share state. See Application Configuration.Migrated to label-based hardware identification across configurations and on-disk storage. Implementation key strings became labels keyed off the runtime hardware configuration. See Data Storage.
Added a
markers.csvfile written under each experiment directory recording the active marker channel definitions for the run. See Data Storage.Added the
RfConfigSnapshothelper for serializing the full RF configuration with each experiment. See RF Configuration.
Python companion module
Hardened
BCFTMWandBCFidagainst schema drift across the v1 and v2 on-disk formats: window-function dispatch is driven by an explicit name →scipy.signalmap, sideband selection accepts both numeric and string forms,FtUnitsaccepts both numeric andFtV/FtmV/FtuV/FtnVforms, and a single helper centralizes the dual-form parse used by every enum-bearing field. Unknown enum values raiseValueErrorrather than falling through to a silent default. See BCFid and BCFTMW (10bd9d08).BCExperimentreadsmarkers.csvwhen present and exposes the active marker channel definitions as amarkersDataFrame attribute. Thehardware.csvreader accepts both the legacysubKeyand the currentdriversecond-column headers, and tolerates the historicalhardwareTypecolumn being numeric, string, or absent — so v1 fixtures continue to load alongside v2 captures. See BCExperiment (10bd9d08).Added a differential-FID API on
BCFTMW:is_multi_segment,num_backups, andget_differential_fid(start, end)produce aBCFidwhose data and shot count reflect the cumulative FID between two backup points infidparams.csv, withvmultscaling recomputed from the bounding entries. See BCFTMW (10bd9d08).Added optional axis-unit selection on
BCFid.x,BCFid.xy,BCFid.ft, andBCFTMW.process_sideband. Time axes accepts/ms/us/μs/nsand frequency axes acceptHz/kHz/MHz/GHz/THz; intensities and the user-facing μs/MHz gate keyword arguments are unchanged. See BCFid (9285f0f8).Added
BCLIFandBCLifTracefor LIF read and processing, mirroring the C++LifTracesemantics.BCLifTraceexposes per-tracesmooth(IIR low-pass plus Savitzky–Golay) andintegrate(sample-space trapezoidal sum, with reference-channel ratio when a reference is present);BCLIFprovidesdelay_axis/laser_axis,delay_slice/laser_slice, andimageaggregating helpers with configurablefill=np.nan|0.0for missing scan points. See BCLIF and BCLifTrace (dc7e7640).Restructured the Sphinx documentation into per-class pages matching the C++ API reference layout, refreshed
single-fid.ipynbagainst the v2 schema, and added a fully executedsingle-lif.ipynbcovering trace loading, smoothing, integration, slice extraction, and 2-D image rendering. See Python Module (7cb8ab84).Added multi-experiment FID coaveraging via the new
coaverage_fidsandcoaverage_spectramodule-level functions.coaverage_fidsproduces aBCFidwhose raw integer data is the sample-by-sample sum of the inputs and whose shot count is the sum of input shot counts, with optional cross-correlation phase correction against a chosen reference window.coaverage_spectrareturns a shot-weighted magnitude-spectrum coaverage. Both refuse on any mismatch inspacing,size,sideband,probefreq,vmult, or frame count. See BCFid.Tagged the package as
0.1.0rc1on PyPI.pip install blackchirpcontinues to resolve to the prior stable release; testers opt in withpip install --pre blackchirporpip install blackchirp==0.1.0rc1(4a9b69d0).
Bug fixes
Hardware.
Fixed inverted marker bit-packing on the AWG70002A and AWG7122B (ba07d008).
Fixed common-LO clock persistence and clock-frequency signal chaining (836b7750).
Fixed the Apply Clock Settings button so clock changes can be pushed without closing the dialog (cd07dd5f).
Fixed aux-data registration key mismatches in the flow controller and temperature controller paths and corrected the resulting plot labels (79dfe7e8, 8e67bebb, 8458aad9).
Fixed flow-controller channel display and the underlying destructor; refined the gas-flow display layout (e53d7f90, eb8d7fbc, 6783af97).
Fixed the flow-controller poll loop and the Python template- copy workflow (63fee23d).
Fixed Python hardware experiment aux-data emission and host- script deployment (dfb57021).
Fixed threaded hardware destructors not running on shutdown:
~HardwareManagerjoined each worker thread but never deleted the moved-to-thread object, so settings persisted by~SettingsStorage::save()(such as flow-controller channel names onPythonFlowController) were silently dropped on exit (e0acf07d).Fixed a destruction race during application close when a Python hardware driver was actively polling:
PythonProcess::sendRequestran a nestedQEventLoopon the hardware thread to service relay requests, and shutdown could destroy the driver while that loop was in flight, so the post-loopisRunning()check dereferenced a dangling pointer and the process segfaulted out of theFlowControllerpoll path. Quiesce poll timers via a newHardwareObject::prepareForShutdown()virtual invoked before worker-thread teardown, with aQPointerguard around the nested loop for the residual case (70fdc9ad).Fixed the flow-controller poll interval not refreshing when the user changed it in the Hardware Settings dialog: the
PythonFlowControllertrampoline overrodereadSettingswithout chaining toFlowController::readSettings, so the base-class timer reload was silently bypassed. Restructured the contract as a non-virtual interface —HardwareObjectexposeshwReadSettingsas the sole entry point, each intermediate hardware basefinal-overrides it and dispatches to a per-base hook (fcReadSettings,pcReadSettings,tcReadSettings,pgReadSettings,awgReadSettings,clockReadSettings,ftmwReadSettings,gpibReadSettings,ioReadSettings,lifLaserReadSettings,lifDigitizerReadSettings) — so a derived driver that forgets to chain becomes a compile error rather than a silent runtime omission (d512ee5e).
Hardware configuration.
Fixed loadout persistence and timestamp handling on save (1c9586b2, f8e83611).
Fixed the
SettingsStoragenested-group wipe that affected FTMW preset CRUD (3d73f08d).Fixed several runtime-hardware-config defects: protocol registry initialization, vtable crashes during hardware destruction, and a deadlock in the configuration dialog (68e49ab2).
Fixed multiple Runtime Hardware Configuration Dialog defects (7a299892, aced0817, ed915a93, d66aa076).
Fixed
BC_ALLHARDWAREbuild errors and the LIF logic underBC_ALLHARDWARE(0bfe75c0, fe7b5f0a).Fixed GPIB protocol configuration and connection testing (cfd85d62).
Fixed Communication Settings dialog and clock-manager initialization (19f60cf6, d733af0d).
Fixed vendor-library search priority and the library browse dialog (1c4f6604).
Fixed
QVariantenum serialization and duplicate error messages when switching protocols (f7e3d6f7).Fixed optional-hardware configuration init and wizard page population (be8a82e2).
Acquisition.
Fixed chirp recalculation and RF-config loss in the experiment wizard (1483a2d7).
Fixed a minor
FtmwViewWidgetrendering glitch under heavy processing load (637d6d4e).Fixed a long-standing crash on LIF-only experiments when the backup interval was set to a non-zero value: the backup scheduler dereferenced the unallocated FTMW configuration. LIF data is segment-flushed at acquisition time, so backup is now skipped for non-FTMW experiments (f335b11d).
Tooling.
Fixed an intermittent crash on closing
blackchirp-viewer(446a5c0a).Made
ZoomPanPlotcurve attach and detach thread-safe via a curve registry, eliminating a class of races that surfaced in both the main application and the viewer (af4aab85).Fixed additional
ZoomPanPlotdefects surfaced during the API-reference work (feb21753).
User interface.
Fixed
ScientificSpinBoxnot displaying an initial value of0.0(00b0608d).Fixed overlays and aux data never persisting for experiments opened by path: the disk-loading
Experimentconstructor passed the placeholder number rather than the header-resolved one to its sub-storages, andOverlayStoragegates all disk writes on a valid experiment number (5a595db8).Fixed catalog overlays always rendering as a step plot and overwriting the saved curve style on every load. The stick-plot style is now a creation-time default, so switching a convolved catalog to a line plot survives reloads (1f473d60).
Fixed the overlay Configure dialog silently erasing an existing comment because the comment field was never populated from the overlay before the dialog wrote it back (286fe2fe).
Fixed a stray duplicate checkbox appearing in the overlay table when toggling visibility: the paint-based delegate also created a real checkbox editor (175e66b3).
Fixed a “pure virtual method called” crash when removing an overlay while a plot filter pass was in flight; the curve is now drained and unregistered before destruction (b82736e6).
Fixed the Peak Find Remove control doing nothing: the button’s clicked signal was never connected, so selected peaks could not be removed from the list (004c523b).
Fixed a use-after-free when a Peak Find pass outlived its widget. The background search discarded its future, so reloading the experiment or tearing down the dock mid-search could free members still in use; the pass is now drained before destruction (9428b017).
Fixed Peak List Export dialog defects: the dipole spin box ignored its enabled setting on load, persisted fractional intensity thresholds were truncated to integers, cancelling the save-file dialog raised a spurious export-failure box, and edits to the shots/intensity table were discarded unless the FTB format was exported (f15eb918).
Fixed the catalog overlay creation dialog leaving the frequency-range filtering controls disabled even after a valid catalog file was selected; they were only editable when reconfiguring an existing overlay (3341b0ad).
Fixed the Generic XY overlay dialog locking the delimiter, header-line, column-mapping, and filtering controls until the file already parsed, so a file that needed manual settings to parse could never be coaxed into parsing. Source-file validity is now existence-based; parse correctness still gates overlay creation (3341b0ad).
Fixed the Generic XY overlay reporting an opaque parser-availability or parse failure. The selected file is always handed to the Generic XY parser, and the failure message states the cause, such as a file containing only one column (3341b0ad).
Python companion module.