Changelog¶
Unreleased¶
Added commands for querying and setting the status led.
Moved documentation hosting from Read the Docs to Codeberg Pages, built via Forgejo Actions and served at https://cge.codeberg.page/qslib/. The Read the Docs site now redirects there.
Version 0.15.2¶
(Generated with LLM assistance.)
Protocol fixes¶
Correct collection-filter attributes in
tcprotocol.xmlfor hacform filter strings.
Communication fixes¶
Treat zero-byte reads as disconnects.
Resynchronize malformed messages at newline boundaries.
Bound response waits and make Python waits interruptible.
End log subscriptions when the connection closes.
Prevent response-channel backpressure from blocking the receive loop or dropping terminal responses.
Report response parse failures when their identifier is recoverable.
Stage identity fixes¶
Add raw stage names to
RunStatusand distinguishPRERUNfromPOSTRUNpositions.Use Polars APIs for Altair stage selection.
Warn when collected-data stage values are nonnumeric.
Version 0.15.1¶
(LLM-generated descriptions below.)
Data fixes¶
Fix
welldata/filter_datatime columns on v1-spec EDS files. In 0.15.0 the v1 codepath was rewritten to go throughfilter_data_polars(which emitsDatetime[ms, UTC]) and reformat back to the legacy pandas multi-index; the timestamp conversion assumedastype("int64")returned nanoseconds, so it divided by 1e9 and produced timestamps 1e6× too small (and huge negativeseconds/hours). Now uses a time-unit-agnostic subtraction from the Unix epoch.Add
temperatures_polars_widefor callers that need the 0.14-era wide schema (timestampasDatetime[ms, UTC], one column per(kind, zone)—sample_1..N,heatsink,cover,block_1..N).temperatures_polarsitself remains long-format (the intentional 0.15 default), now also with atimecolumn derived fromtimestamp.
Version 0.15.0¶
Robustness improvements to communication, consolidation of parsing into Rust, and a new quant/calibration data pipeline:
Communication fixes¶
Fix READY message read to handle partial TCP reads (TCP does not guarantee message boundaries).
Fix double newline on command send when content already has a trailing newline.
Fix quoted string parser to handle backslash escape sequences (
\",\\,\n,\t).Fix ErrorResponse parser to handle errors without brackets.
Fix Rust parser tag character set to include underscore (e.g.
<quote_reply>).Fix DRAW? returning “false” instead of “Open” by not coercing open/closed to Bool in response parser.
Add single-quote string support to Rust parser.
Extend boolean parsing to cover all server-recognized forms (yes/no, on/off, open/close).
Extend command name character set to include
+,-,~,<(e.g.SUBS+,FLAG-).Add WARNing response type to Rust parser.
Add tag stack timeout to message receiver, preventing unclosed tags from absorbing all subsequent messages.
Send QUIT command on disconnect for clean server-side cleanup.
Handle auth-required gracefully in
Machine.connect()with a clear error message for remote connections.Handle
ExclusiveAccessandAccessGivenerrors as specific exception subclasses.
Data and protocol fixes¶
Fix IncrementCycle/IncrementStep defaults to match server (default=2, not 1).
Fix SampleTemperatures separator mismatch in multicomponent data parsing.
Remove overly strict temperature zone and plate type assertions.
Parameterize plate type in
Experiment._new_xml_filesinstead of hardcoding 96-well.
New features¶
Consolidate Python parsing to Rust:
AccessLevel,FilterSet,SCPICommand,PlateSetupall now handled in Rust;pyparsingdependency removed.Add Rust quant/calibration file parsers and filterdata reconstruction from quant + calibrations (matches filterdata.xml to <0.1 error).
Add ROI calibration parsing and TIFF-to-quant processing pipeline (exact match to instrument output).
Migrate
FilterDataCollectionloading and timestamp-setting to Rust.Dynamic zone count querying via
Machine.get_zone_count()instead of hardcoded 6.Expose server random key auth mechanism via
Machine.generate_random_key().Validate READY message capabilities on connection.
Make
subscribe_log()actually send SUBS+ command to the server.Parse MESSage timestamp structurally in
LogMessage.Extend
Subscribecommand builder with timestamp and multi-topic support.Add exclusive and stealth flags to
AccessLevelSetcommand.
Testing¶
~226 new tests across Rust and Python, covering communication, parsing, plate setup, processors, and machine logic.
Security¶
Update
rustls-webpki0.102 → 0.103 to fix four advisories: CRL distribution-point matching (RUSTSEC-2026-0049), URI name-constraint bypass (RUSTSEC-2026-0098), wildcard name-constraint bypass (RUSTSEC-2026-0099), and reachable panic in CRL parsing (RUSTSEC-2026-0104).Bump
bytesto 1.11.1 (integer overflow inBytesMut::reserve, RUSTSEC-2026-0007),quinn-prototo 0.11.14 (QUIC endpoint DoS, RUSTSEC-2026-0037), andtimeto 0.3.47 (stack-exhaustion DoS, RUSTSEC-2026-0009).Port
qs-monitorfrommatrix-sdk0.9 to 0.16, fixing three advisories: encrypted-event sender spoofing (RUSTSEC-2025-0041), panic inRoomMember::normalized_power_level()(RUSTSEC-2025-0065), and DoS via customm.room.join_rulesevents (RUSTSEC-2025-0135).
Build¶
Vendor
matrix-sdk0.16 with#![recursion_limit = "512"]added to work around rust-lang/rust#152942 (query-depth overflow on rustc 1.94+ due to matrix-sdk’s deeply nested#[tracing::instrument]async chain picking up an extraManuallyDroplayer).qs-monitor/src/main.rsgets the same attribute to raise the trait-solver limit forSend-ness ofClient::sync()when passed totokio::spawn.
CI¶
Bump GitHub Actions past the Node.js 20 deprecation:
actions/checkoutv4→v6,setup-pythonv5→v6,upload-artifactv4→v7,download-artifactv4→v8,extractions/setup-justv2→v4,astral-sh/setup-uvv7→v8.1.0,codecov/codecov-actionv5→v6.Fix wheel-test jobs on Linux:
RUSTC_WRAPPER=sccachewas leaking frommaturin-actioninto subsequentuv syncinvocations where sccache isn’t on PATH, failing silently on macOS (sccache pre-installed) but breaking Linux. Now overridden per-step.Drop macOS x86_64 (Intel) from the wheel matrix (<8 Darwin downloads/month across all arches on PyPI).
Version 0.14.0¶
A significant reorganization:
Core communication and parsing code in Rust.
Polars dataframe support, in addition to pandas.
A new, rust-based qs-monitor with improved reliability and a matrix bot with commands.
Altair plotting support.
Numerous bug fixes and improvements.
Python 3.10 is now the minimum supported Python.
Version 0.13.0¶
Add
PlateSetup.from_picklistmethod to generate a PlateSetup from a Kithairon PickList, if Kithairon is installed.Improve ssl support for monitor.
Have monitor complain to matrix if it exits unexpectedly.
Fix compile_eds when there is no folder to compile (if, eg, something else has already compiled the EDS).
Version 0.12.0¶
Machine.blockcommand to directly control block temperatures.Certificate support for SSL, and new connection recommendations.
Stage lines and event spans now are now not plotted if they are outside of the selected time range / stages.
Stepnow supports repeats.Stage.stepped_rampcan now take multiple data points per temperature.Fix hanging connection bug.
Version 0.11.0¶
Initial support for 384-well blocks, at least in data/file reading.
Initial support for v2.0 EDS specification machines (eg, QS6Pro), at least in data/file reading.
Parsing of multicomponent data for v1 and v2 machines, and partial analysis data for v1 machines.
Available data is shown in experiment information.
Change license to EUPL-1.2.
Fixes for new matplotlib versions.
Support for Python 3.12.
Version 0.10.1¶
SSL/non-SSL autoconnection speed improvements
Drawer/cover annotation improvements
Version 0.10.0¶
Add annotations to plots for drawer and cover open and close events.
Add support for SSL / firmware 1.3.4.
Version 0.9.4¶
Fix multi-temperature plotting bug.
Version 0.9.3¶
Update dependencies, convert to pyproject.toml.
Fix cycle selection and direct pandas selection for normalization processes.
Version 0.9.2¶
Fix a communications bug where a packet that can cause commands to hang in certain rare situations.
Version 0.9.1¶
Minor bug fixes and dependency updates (to fix pandas errors).
Fixes to support Pandas 2.0.
Ensure that some invalid characters are not used in machine names.
Check for files with and without spaces on machine when loading a new experiment (in case run was started outside of qslib).
Parse IOError messages from the machine.
Version 0.9.0¶
Fix
Stage.stepped_rampwhen all temperature increments are the same, but temperatures are not.Add a
start_incrementoption toStage.stepped_rampfor cases where the user does not want the ramp to actually start at the starting temperature, but at the first increment away from it (eg, when continuing a previous ramp).Ensure that units are delta units when appropriate in protocols, regardless of whether the user entered them as delta units (eg, so “2°C” will work as a temperature step).
Version 0.8.2¶
Add check for existing, completed EDS files with same name, and option to
Experiment.runto overwrite completed or working files.Fix XML protocol parsing bug for increment units with non-qslib EDS files.
Fix stage lines in plots.
Improve error messages.
Version 0.8.1¶
Fix bug with BytesIO not being recognized by
Experiment.save_file.
Version 0.8.0¶
Ensure that protocols don’t have incorrect stage index and label information when being sent to machine.
MachineStatus now includes temperature information, as does the
qslib machine-statusCLI command.Experiment.sync_from_machinecan exclude tiffs, and has better logging.Custom steps are now approximated in xml files, keeping them somewhat compatible with the machine’s android interface.
Several testing and documentation improvements.
Python 3.11 fixes.
Version 0.7.1¶
QSLib-initiated experiments should now be partially compatible with the machine’s android interface. Status, time, and the (possibly approximate) protocol should be displayed. Data and samples will likely not. Pause/resume/stop/open/close buttons on the interface should function properly.
Processorand plotting improvements.
Version 0.7.0¶
Protocolnow hasProtocol.stage, and Stage now hasStage.step, to provide convenient, 1-indexed access, such thatprotocol.stage[5]of is stage 5 ofprotocol, not stage 6.Protocolnow supports setting PRERUN and POSTRUN stages, as a series of SCPI commands. This allows the setting of things like idling temperatures and exposure times. It is not easily usable yet, however.Experiment.change_protocol_from_nowallows convenient changes to a currently-running experiment.Normalizationhas been renamed toProcessor. Plotting functions can take sequences of processors to process data. These now include:Normalization as before:
NormByMeanPerWell,NormByMaxPerWellSubtractMeanPerWell: subtracts the mean of a particular region, applied to each well.SmoothEMWMean: smooths data using Pandas’ ExponentialMovingWindow.mean.SmoothWindowMean: smooths data using Pandas’ Rolling.mean or Window.mean.
Some initial implementation changes to allow repeated steps (not stages).
Fixes bug that prevented loading of some aborted runs.
Fixes monitor’s recording of temperatures.
Experiment.all_filters uses data if it exists; Experiment.filter_strings as a convenience function alternative.
SCPICommand parsing improvements.
Protocol printing improvements.
Version 0.6.3¶
Fixes drawer check bug.
Version 0.6.2¶
Add checks for cover and drawer position after changing positions.
Version 0.6.1¶
Fix pyparsing 3.0.7 whitespace parsing problem (pyparsing/pyparsing#359).
Use Hypothesis for some tests.
Version 0.6.0¶
Improved plots, including new
Experiment.plot_temperatures.Comments in SCPI commands, allowing save/load of default filters in protocols
Licensing switched to AGPL 3.0, CLA in docs.
Command comment parsing, also used to store whether steps are using default filters.
Example notebook
Working parsing of Exposure commands
Dependency version fixes
Version 0.5.1¶
CustomStep.collect(and subclasses, includingStep) is nowCustomStep.collects. Thecollectparameter forStepcan now beNone, which will collect data if the step has a filter setting (ie, if you want to collect the defaultProtocolfilters, you need to usecollect=True).Stage.stepped_rampandStage.hold_forare now safer in requiring some keyword arguments, are documented, and are more flexible.
Version 0.5.0¶
Units throughout protocols, thanks to Pint: you can now use strings like ‘1 hr’ or ‘52 °C’ when defining protocols.
Automatic connections throughout Machine and Experiment, by default.
Change safe titles from spaces-as-“-” to spaces-as-“_”, consistent with machine.
Deprecated paramiko tunnel.
Documentation rewrite
Implement EDS-file (in-progress and complete) synchronization for monitor.
Reorganization of modules: common is no longer needed
Version 0.4.1¶
Allow setting of Experiment.sample_wells.
Improve plotting code.
Version 0.4.0¶
Much faster
Experiment.sync_from_machine, only transferring additional log entries rather than the entire log.Common plotting routines for fluorescence data.
More reliable monitoring.
More reliable connections, and testing.
Stage.stepped_rampconvenience function.Fixes to bugs inhibiting exposure setting, and some basic implementations for this.
Fixes to qs-monitor for cycle counts > 999 (and other large stage / step / cycle counts).
Version 0.3.1¶
CLI improvements.
Fix qs-monitor and various functions when run titles have spaces in them.
Improve tests and typing.
Version 0.3.0¶
Add qslib CLI, with some basic utility functions.
Include calculation using 1.6°c/s ramp (standard mode default) in temperature protocols, initiating from 25°c. This makes experiment temperature data match reasonably well with protocol calculations. It needs to be expanded to handle different ramp rates and run modes, however.
Added some tests.
Version 0.2.0¶
Add internal SSH tunnel support, so that this doesn’t need to be set up separately, and can be configured with parameters to Machine.
Fix mid-run syncing bugs related to directory creation.
Handle some different inputs for Protocol creation.
Try to handle spaces in names better; this is still a problem, howver.
Version 0.1.1¶
Various small improvements and bug fixes.
Version 0.1.0¶
Initial implementation of full communication (OK/NEXT/ERRor), Experiment files, Machine connection interface. Adaptation of QSConnectionAsync to use new communication. Move of monitor system into qslib.
Version 0.0.0 / etc¶
Initial version of QSConnectionAsync and other low-level portions to support rawquant and qpcr_data_updater.