qslib package¶
Submodules¶
qslib.cli module¶
- exception qslib.cli.NoAccess[source]¶
Bases:
BaseException
- exception qslib.cli.NoNewAccess[source]¶
Bases:
BaseException
qslib.common module¶
qslib.data module¶
qslib.experiment module¶
Experiment class and related.
- exception qslib.experiment.AlreadyExistsCompleteError(machine, name)[source]¶
Bases:
AlreadyExistsErrorA run already exists in uncollected (experiment:) with the same name.
- name: str¶
- exception qslib.experiment.AlreadyExistsError(machine, name)[source]¶
Bases:
MachineErrorA run already exists with the same name.
- name: str¶
- exception qslib.experiment.AlreadyExistsWorkingError(machine, name)[source]¶
Bases:
AlreadyExistsErrorA run already exists in uncollected (experiment:) with the same name.
- name: str¶
- exception qslib.experiment.AlreadyStartedError(name, state)[source]¶
Bases:
ValueErrorThe experiment has already been started.
- exception qslib.experiment.DataLoadingError(name, message, cause)[source]¶
Bases:
ExceptionThe data could not be loaded.
- exception qslib.experiment.DataNotAvailableError(name, message)[source]¶
Bases:
ExceptionThe data is not available.
- class qslib.experiment.Experiment(name=None, protocol=None, plate_setup=None, _create_xml=True)[source]¶
Bases:
objectA QuantStudio experiment / EDS file
This class can create, modify, load and save experiments in several ways, run them, and control and modify them while running.
Experiments can be loaded from a file:
>>> exp: Experiment = Experiment.from_file("experiment.eds")
They can also be loaded from a running experiment:
>>> machine = Machine("localhost", password="password") >>> exp = Experiment.from_running(machine)
Or from the machine’s storage:
>>> exp = Experiment.from_machine(machine, "experiment")
They can also be created from scratch:
>>> exp = Experiment("an-experiment-name") >>> exp.protocol = Protocol([Stage([Step(time=60, temperature=60)])]) >>> exp.plate_setup = PlateSetup({"sample_name": "A5"})
And they can be run on a machine:
>>> exp.run(machine)
Data can be accessed in a few ways:
The (hopefully) easiest way is with welldata, which has multi-indexes for both rows and columns.
>>> exp.welldata.loc[('x1-m4', 4), [('time', 'hours'), ('A05', 'fl')]].plot()
Or for a temperature curve:
>>> exp.welldata.loc[('x1-m4', 4), [('A05', 'st'), ('A05', 'fl')]].plot()
filterdata should still work normally.
Notes
There are a few differences in how QSLib and AB’s software handles experiments.
AB’s software considers the run as starting when the machine indicates “Run Starting”. This is stored as
runstarttimein QSLib, but as it may include the lamp warmup (3 minutes) and other pre-actual-protocol time, QSLib instead prefersactivestarttime, which it sets from the beginning of the first real (not PRERUN) Stage, at which point the machine starts its own active clock and starts ramping to the first temperature. QSLib uses this as the start time reference in its data, and also includes the timestamp from the machine.The machine has a specific language for run protocols. QSLib uses this language. AB’s Design and Analysis software does not, instead using an XML format. Not everything in the machine’s language is possible to express in the XML format (eg, disabling pcr analysis, saving images); the XML format has some concepts not present in the machine format, and is generally more complicated and harder to understand. QSLib uses and trusts the machine’s protocol if at all possible, even for files written by AB D&A (it is stored in the log if the run has started).
QSLib will try to write a reasonable XML protocol for AB D&A to see, but it may by an approximation or simply wrong, if the actual protocol can’t be expressed there. It will also store the actual protocol in tcprotocol.xml, and its own representation.
By default, creating a step with a per-cycle increment in QSLib starts the change on cycle 2, not cycle 1, as is the default in the software.
Immediate pause/resume, mid-run stage addition, and other functions are not supported by AB D&A and experiments using them may confuse the software later.
QSLib writes notes to XML files, and tries to create reasonable XML files for AB D&A, but may still cause problems. At the moment, it makes clear that its files are its own (setting software versions in experiment.xml and Manifest.mf).
- abort(machine=None)[source]¶
If this experiment is running, abort it, stopping it immediately.
Requires and takes exclusive Controller access on the machine.
- Raises:
NotRunningError – the experiment is not currently running
- Return type:
-
activeendtime:
datetime|None¶ The actual end of the main part of the run, indicated by “Stage POSTRun” or an abort.
-
activestarttime:
datetime|None¶ The actual beginning of the first stage of the run, defined as the first “Run Stage” message in the log after “Stage PRERUN”. This is not what AB’s software considers the start of a run.
- property all_filters: Collection[FilterSet]¶
All filters used at some point in the experiment.
If the experiment has data, this is based on the existing data. Otherwise, it is based on the experiment protocol.
- property amplification_data: DataFrame¶
- property analysis_result: DataFrame¶
- property calibrations: dict¶
Calibration data parsed from the EDS calibrations directory.
Returns a dict with keys ‘uniformity’, ‘background’, and optionally ‘puredye’.
- change_protocol(new_protocol, machine=None, force=False)[source]¶
For a running experiment and an updated protocol, check compatibility with the current run, and if possible, update the protocol in the experiment file and on the machine, changing the current run.
Changes that should be possible:
Changing the number of cycles of the current run to a higher or lower value (but higher or equal to the current cycle number), allowing stages to be lengthened, shortened, or stopped.
Adding new stages after the current stage.
Arbitrarily changing any stage that hasn’t started.
For safest results, ensure power saving is turned off in the Android software.
- change_protocol_from_now(new_stages, machine=None)[source]¶
- Return type:
For a running experiment, change the remaining stages to be the provided :param:`new_stages` list. This is a convenience function that:
Gets the currently-running stage and cycle.
Sets the repeat number of the current stage to its current cycle, thus ending it after the end of the current cycle.
Changes the remainder of the stages to be those in the :param:`new_stages` list.
Because this does not impact any current or past stages, there is less of a need to ensure that the stages provided are compatible with the old protocol. The only check done is to ensure that, if the provided stages have any collection commands using default filters, the old protocol has specified default filters. This function does not allow the default filters to be changed: if you want to use filters other than the defaults, or defaults were not provided in the old protocol, then either specify filters explicitly (recommended) for new stages you’d like to be different, or use
Experiment.change_protocoldirectly.
- data_for_sample(sample)[source]¶
Convenience function to return data for a specific sample.
Finds wells using
self.plate_setup.sample_wells[sample], then returnsself.welldata.loc[:, wells]- Parameters:
sample (str) – sample name
- Returns:
Slice of welldata. Will have multiple wells if sample is in multiple wells.
- Return type:
pd.Dataframe
- property events: DataFrame¶
- property filter_data: DataFrame¶
- property filter_data_polars: DataFrame¶
- property filter_strings: list[str]¶
All filters, as x?-m? strings, used at some point in the experiment.
- classmethod from_file(file)[source]¶
Load an experiment from an EDS file.
- Returns:
file – The filename or file handle to read.
- Return type:
str or os.PathLike[str] or IO[bytes]
- Raises:
ValueError – if the file does not appear to be an EDS file (lacks an experiment.xml).
- classmethod from_machine(machine, name)[source]¶
Create an experiment from data on a machine, checking the running experiment if any, the machine’s public_run_complete storage, and the machine’s uncollected storage.
- Parameters:
- Returns:
a copy of the experiment
- Return type:
- classmethod from_machine_storage(machine, name)[source]¶
Create an experiment from the machine’s storage.
- Parameters:
- Returns:
a copy of the experiment
- Return type:
- classmethod from_running(machine)[source]¶
Create an experiment from the one currently running on a machine.
- Parameters:
machine (Machine) – the machine to connect to
- Returns:
a copy of the running experiment
- Return type:
- classmethod from_uncollected(machine, name, move=False)[source]¶
Create an experiment from the uncollected (not yet compressed) storage.
- Parameters:
- Returns:
a copy of the experiment
- Return type:
- get_status(machine=None)[source]¶
Return the status of the experiment, if currently running.
Requires Observer access on the machine.
- Raises:
NotRunningError – the experiment is not currently running
- Return type:
- info(format='markdown', plate='list')[source]¶
Generate a summary of the experiment, with some formatting configuation. str() uses this with default parameters.
- Parameters:
format ("markdown" or "org", optional) – Format of output, currently “markdown” or “org”, and currently matters only when plate is “table”. By default “markdown”. If an unknown value, passed as tablefmt to tabulate.
plate ("list" or "table", optional) – Format of plate information. “list” gives a list of samples, “table” outputs a plate layout table (possibly quite wide). By default “list”.
- Returns:
Summary
- Return type:
- info_html()[source]¶
Create a self-contained HTML summary (returned as a string, but very large) of the experiment.
- Return type:
- property multicomponent_data: DataFrame¶
- pause_now(machine=None)[source]¶
If this experiment is running, pause it (immediately).
Requires and takes exclusive Controller access on the machine.
- Raises:
NotRunningError – the experiment is not currently running
- Return type:
-
plate_setup:
PlateSetup¶ Plate setup for the experiment.
- plot_anneal_melt(samples=None, filters=None, anneal_stages=None, melt_stages=None, between_stages=None, process=None, normalization=None, ax=None, marker=None, legend=True, figure_kw=None, line_kw=None)[source]¶
Plots anneal/melt curves.
This uses solid lines for the anneal, dashed lines for the melt, and dotted lines for anything “between” the anneal and melt (for example, a temperature hold).
Line labels are intended to provide full information when read in combination with the axes title. They will only include information that does not apply to all lines. For example, if every line is from the same filter set, but different samples, then only the sample will be shown. If every line is from the same sample, but different filter sets, then only the filter set will be shown. Wells are shown if a sample has multiple wells.
- Parameters:
samples (
Union[str,Sequence[str],None]) – A reference to a single sample (a string), a list of sample names, or a Python regular expression as a string, matching sample names (full start-to-end matches only). Well names may also be included, in which case each well will be treated without regard to the sample name that may refer to it. Note this means you cannot give your samples names that correspond with well references. If not provided, all (named) samples will be included.filters (
Union[str,FilterSet,Collection[str|FilterSet],None]) – Optional. A filterset (string or FilterSet) or list of filtersets to include in the plot. Multiple filtersets will be plotted on the same axes. Optional; if None, then all filtersets with data in the experiment will be included.anneal_stages (int | Sequence[int] | None) – Optional. A stage or list of stages (integers, starting from 1), corresponding to the anneal, melt, and stages between the anneal and melt (if any). Any of these may be None, in which case the function will try to determine the correct values automatically.
melt_stages (int | Sequence[int] | None) – Optional. A stage or list of stages (integers, starting from 1), corresponding to the anneal, melt, and stages between the anneal and melt (if any). Any of these may be None, in which case the function will try to determine the correct values automatically.
between_stages (int | Sequence[int] | None) – Optional. A stage or list of stages (integers, starting from 1), corresponding to the anneal, melt, and stages between the anneal and melt (if any). Any of these may be None, in which case the function will try to determine the correct values automatically.
normalization (
Optional[Processor]) – Optional. A Normalizer instance to apply to the data. By default, this is NormRaw, which passes through raw fluorescence values. NormToMeanPerWell also works well.ax (
Optional[Axes]) – Optional. An axes to put the plot on. If not provided, the function will create a new figure, by default with constrained_layout=True, though this can be modified with figure_kw.marker (
Optional[str]) – The marker format for data points, or None for no markers (default).legend (
Union[bool,Literal['inset','right']]) – Whether to add a legend. True (default) decides whether to have the legend as an inset or to the right of the axes based on the number of lines. “inset” and “right” specify the positioning. Note that for “right”, you must use some method to adjust the axes positioning: constrained_layout, tight_layout, or manually reducing the axes width are all options.figure_kw (
Optional[dict[str,Any]]) – Optional. A dictionary of options passed through as keyword options to the figure creation. Only applies if ax is None.line_kw (
Optional[dict[str,Any]]) – Optional. A dictionary of keywords passed to all three plotting commands.
- Return type:
- Returns:
Axes – The axes object of the plot.
- plot_over_time(samples=None, filters=None, stages=slice(None, None, None), process=None, normalization=None, ax=None, legend=True, temperatures='axes', marker=None, stage_lines=True, annotate_stage_lines=True, annotate_events=True, figure_kw=None, line_kw=None, time_units='h')[source]¶
Plots fluorescence over time, optionally with temperatures over time.
Line labels are intended to provide full information when read in combination with the axes title. They will only include information that does not apply to all lines. For example, if every line is from the same filter set, but different samples, then only the sample will be shown. If every line is from the same sample, but different filter sets, then only the filter set will be shown. Wells are shown if a sample has multiple wells.
- Parameters:
samples (str | Sequence[str] | None) – A reference to a single sample (a string), a list of sample names, or a Python regular expression as a string, matching sample names (full start-to-end matches only). Well names may also be included, in which case each well will be treated without regard to the sample name that may refer to it. Note this means you cannot give your samples names that correspond with well references. If not provided, all (named) samples will be included.
filters (str | FilterSet | Collection[str | FilterSet] | None) – Optional. A filterset (string or FilterSet) or list of filtersets to include in the plot. Multiple filtersets will be plotted on the same axes. Optional; if None, then all filtersets with data in the experiment will be included.
stages (slice | int | Sequence[int]) – Optional. A stage, list of stages, or slice (all using integers starting from 1), to include in the plot. By default, all stages are plotted. For example, to plot stage 2, use stages=2; to plot stages 2 and 4, use stages=[2, 4], to plot stages 3 through 15, use stages=slice(3, 16) (Python ranges are exclusive on the end). Note that is a slice, you can use None instead of a number to denote the beginning/end.
normalization (PolarsProcessor | None) – Optional. A Normalizer instance to apply to the data. By default, this is NormRaw, which passes through raw fluorescence values. NormToMeanPerWell also works well.
temperatures (Literal[False, ‘axes’, ‘inset’, ‘twin’]) –
Optional (default “axes”). Several alternatives for displaying temperatures. “axes” uses a separate axes (created if ax is not provided, otherwise ax must be a list of two axes).
Temperatures are from Experiment.temperature, and are thus the temperatures as recorded during the run, not the set temperatures. Note that this has a very large number of data points, something that should be dealt with at some point.
ax (Axes’ | ‘Sequence[Axes]’ | None) – Optional. An axes to put the plot on. If not provided, the function will create a new figure, by default with constrained_layout=True, though this can be modified with figure_kw. If temperatures=”axes”, you must provide a list or tuple of two axes, the first for fluorescence, the second for temperature.
marker (str | None) – The marker format for data points, or None for no markers (default).
legend (bool | Literal[‘inset’, ‘right’]) – Whether to add a legend. True (default) decides whether to have the legend as an inset or to the right of the axes based on the number of lines. “inset” and “right” specify the positioning. Note that for “right”, you must use some method to adjust the axes positioning: constrained_layout, tight_layout, or manually reducing the axes width are all options.
stage_lines (bool | Literal[‘fluorescence’, ‘temperature’]) – Whether to include dotted vertical lines on transitions between stages. If “fluorescence” or “temperature”, include only on one of the two axes.
annotate_stage_lines (bool | float | Literal[‘fluorescence’, ‘temperature’] | Tuple[Literal[‘fluorescence’, ‘temperature’], float]) – Whether to include text annotations for stage lines. Float parameter allows setting the minimum duration of stage, as a fraction of total plotted time, to annotate, in order to avoid overlapping annotations (default threshold is 0.05).
annotate_events (bool) – Whether to include annotations for events (drawer open/close, cover open/close).
figure_kw (dict[str, Any] | None) – Optional. A dictionary of options passed through as keyword options to the figure creation. Only applies if ax is None.
line_kw (dict[str, Any] | None) – Optional. A dictionary of keywords passed to fluorescence plot commands.
- Return type:
Sequence[Axes]
- plot_over_time_altair(samples=None, filters=None, stages=None, process=(), start_time='experiment', duration_units='hours', show_legend=True)[source]¶
- plot_protocol(ax=None)[source]¶
A plot of the temperature and data collection points in the experiment’s protocol.
- plot_temperatures(*, sel=None, times=None, ax=None, stage_lines=True, annotate_stage_lines=True, annotate_events=True, legend=False, figure_kw=None, line_kw=None, time_units='h', method='matplotlib')[source]¶
Plot sample temperature readings.
- Parameters:
sel (
Optional[Expr]) – A selector for the temperature DataFrame. This is not necessarily easy to use; times is an easier alternative.times (
Optional[tuple[float,float]]) – Constructs a selector to show temperatures for a time range (after activestarttime). :param:`sel` should not be set. Time is in the units of :param:`time_units`.time_units (
Literal['h','m','s']) – The units of the time range, and units to plot. “h” for hours, “m” for minutes, “s” for seconds.ax (
Optional[Axes]) – Optional. An axes to put the plot on. If not provided, the function will create a new figure, by default with constrained_layout=True, though this can be modified with figure_kw.stage_lines (
bool) – Whether to include dotted vertical lines on transitions between stages.annotate_stage_lines (
bool|float) – Whether to include text annotations for stage lines. Float parameter allows setting the minimum duration of stage, as a fraction of total plotted time, to annotate, in order to avoid overlapping annotations (default threshold is 0.05).annotate_events (
bool) – Whether to include annotations for events (cover opening/closing, drawer opening/closing).legend (
bool) – Whether to add a legend.figure_kw (
Optional[Mapping[str,Any]]) – Optional. A dictionary of options passed through as keyword options to the figure creation. Only applies if ax is None.line_kw (
Optional[Mapping[str,Any]]) – Optional. A dictionary of keywords passed to plot commands.method (
Literal['matplotlib','altair'])
- Return type:
- property quant_data_from_tiffs_polars: DataFrame¶
Quant data computed from TIFF images + ROI calibration.
Produces the same DataFrame as quant_data_polars but always uses TIFF images rather than pre-computed .quant files.
- property quant_data_polars: DataFrame¶
Raw quant data as a Polars DataFrame.
Uses pre-computed .quant files if available, otherwise falls back to computing from TIFF images + ROI calibration.
- property raw_data: DataFrame¶
- resume(machine=None)[source]¶
If this experiment is running, resume it.
Requires and takes exclusive Controller access on the machine.
- Raises:
NotRunningError – the experiment is not currently running
- Return type:
- property roi_calibration¶
ROI calibration data parsed from roi.ini.
- run(machine=None, overwrite=False, require_exclusive=False, require_drawer_check=True)[source]¶
Load the run onto a machine, and start it.
- Parameters:
machine (
Union[str,Machine,None]) – The machine to run on, by default None, in which case the machine associated with the run (if any) is used.overwrite (bool or "incomplete", optional) – Whether to overwrite files if a run with the same name already exists. If “incomplete”, only overwrite if the existing run is an incomplete folder (in the experiments: working directory). By default False.
require_exclusive (bool, optional) – Whether to require exclusive access to the machine, by default False.
require_drawer_check (bool, optional) – Whether to ensure the drawer is closed before starting. Note that a close command will be sent regardless of this setting. By default True.
- Raises:
MachineBusyError – The machine isn’t idle.
AlreadyExistsError (either AlreadyExistsWorkingError or AlreadyExistsCompleteError) – The machine already has a folder or eds file with this run name.
- Return type:
-
runendtime:
datetime|None¶ The run end time as a datetime, taken from the log. This is the end of the run,
-
runstarttime:
datetime|None¶ The run start time as a datetime. This is taken directly from the log, ignoring the software-set value and replacing it on save if possibe. It is defined as the moment the machine records “Run Starting” in its log, using its timestamp. This may be 3 minutes before the start of the protocol if the lamp needs to warm up. It should be the same value as defined by AB’s software.
Use
activestarttimefor a more accurate value.None if the file has not been updated since the start of the run
-
runstate:
Literal['INIT','RUNNING','COMPLETE','ABORTED','STOPPED','UNKNOWN']¶ Run state, possible values INIT, RUNNING, COMPLETE, ABORTED, STOPPED(?).
- property runtitle_safe: str¶
Run name with “ “ replaced by “_”; raises ValueError if name has other problematic characters.
- property sample_wells: _SampleWellsView¶
A dictionary of sample names to sample wells (convenience read/write access to the
PlateSetup.
- save_file(path_or_stream='.', overwrite=False, update_files=True)[source]¶
Save an EDS file of the experiment. This should be readable by AB’s software, but makes no attempt to hide that it was written by QSLib, and contains some other information. By default, this will refuse to overwrite an existing file.
- Parameters:
path_or_stream (str or os.PathLike[str] or io.BytesIO) – A filename, open binary IO, or directory. If a directory, the file will be saved with the name from Experiment.runtitle_safe.
overwrite (bool, optional) – If True, overwrite any existing file without warning. Defaults to False.
update_files (bool, optional) – If True (default), update files before saving. Use False if you don’t want qslib to touch the files, for example, if you have just loaded a run from the machine and don’t want qslib to change anything based on its interpretation.
- Return type:
- stop(machine=None)[source]¶
If this experiment is running, stop it after the end of the current cycle.
Requires and takes exclusive Controller access on the machine.
- Raises:
NotRunningError – the experiment is not currently running
- Return type:
- sync_from_machine(machine=None, log_method='eval', include_tiffs=False)[source]¶
Try to synchronize the data in the experiment to the current state of the run on a machine, more efficiently than reloading everything.
- Return type:
- property temperature_ramps_polars: DataFrame¶
- property temperature_setpoints_polars: DataFrame¶
- property temperatures: DataFrame¶
A DataFrame of temperature readings, at one second resolution, during the experiment (and potentially slightly before and after, if included in the message log).
Columns (as multi-index):
- (“time”, …)float
Time of temperature reading, for choices of “timestamp” (Unix timestamp in seconds), “seconds” (seconds since the active start of the run), or “hours”. The latter two may be negative, and may not be set if the run never became active.
- (“sample”, …)float
Sample temperature for blocks 1, 2, …, 6, and average in “avg”.
- (“block”, …)float
Block temperature for blocks 1, 2, …, 6, and average in “avg”.
- (“other”, “cover”)float
Cover temperature
- (“other”, “heatsink”)float
Heatsink temperature
- property temperatures_polars: DataFrame¶
Long-format temperature log (one row per (timestamp, zone, kind)) with columns
timestamp(float seconds since epoch),temperature,zone(1-indexed, null for heatsink/cover),kind(one of “sample”, “block”, “heatsink”, “cover”), andtime(Datetime[ms, UTC]).For the 0.14-era wide schema with one column per zone, use
temperatures_polars_wide.
- property temperatures_polars_wide: DataFrame¶
a single row per timestamp with one column per (kind, zone) —
sample_1..N,heatsink,cover,block_1..N— andtimestampasDatetime[ms, UTC].The default
temperatures_polarsis long-format (one row per zone × kind); use this accessor if you need the legacy wide shape.- Type:
Wide-format temperature log matching the 0.14 schema
- property tiff_images: dict¶
Raw TIFF images as numpy arrays, keyed by (stage, cycle, step, point, filter_set, exposure_index).
Returns a dict mapping tuple keys to numpy uint16 arrays of shape (height, width).
- property welldata: DataFrame¶
A DataFrame with fluorescence reading information.
Deprecated since version 0.14.0: Use
filter_datainstead.Indices (multi-index) are (filter_set, stage, cycle, step, point), where filter_set is a string in familiar form (eg, “x1-m4”) and the rest are int.
Columns (as multi-index):
- (“time”, …)float
Time of the data collection, taken from the .quant file. May differ for different filter sets. Options are “timestamp” (unix timestamp in seconds), “seconds”, and “hours” (the latter two from the active start of the run).
- (well, option)float
Data for a well, with well formatted like “A05”. Options are “rt” (read temperature from .quant file), “st” (more stable temperature), and “fl” (fluorescence).
- (“exposure”, “exposure”)float
Exposure time from filterdata.xml. Misleading, because it only refers to the longest exposure of multiple exposures.
- exception qslib.experiment.MachineBusyError(machine, current)[source]¶
Bases:
MachineErrorThe machine is busy.
- current: RunStatus¶
- exception qslib.experiment.MachineError(machine)[source]¶
Bases:
ExceptionBase class for an error from a machine.
- host: str¶
- machine: InitVar[Machine]¶
- port: int | str | None¶
- exception qslib.experiment.NotRunningError(machine, run, current)[source]¶
Bases:
MachineErrorThe named experiment is not currently running.
- current: RunStatus¶
- run: str¶
qslib.machine module¶
- class qslib.machine.FileListInfo[source]¶
Bases:
TypedDictInformation about a file when verbose=True
- class qslib.machine.FilterDataFilename(filterset, stage, cycle, step, point)[source]¶
Bases:
object-
filterset:
FilterSet¶
-
filterset:
- class qslib.machine.Machine(host, password=None, automatic=True, max_access_level=AccessLevel.Controller, port=None, ssl=None, client_certificate_path=None, client_key_path=None, server_ca_file=None, tls_server_name=None, _initial_access_level=AccessLevel.Observer)[source]¶
Bases:
objectA connection to a QuantStudio machine. The connection can be opened and closed, and reused. A maximum access level can be set and changed, which will prevent the access level from going above that level.
By default, the class tries to handle connections and access automatically.
- Parameters:
host (
str) – The host name or IP to connect to.password (
Optional[str]) – The password to use. Note that this class does not obscure or protect the password at all, because it should not be relied on for security. See Security Considerations for more information.automatic (
bool) – Whether or not to automatically handle connection, disconnection, and where possible, access level. Default True.max_access_level ("Observer", "Controller", "Administrator", or "Full") – The maximum access level to allow. This is not the initial access level, which will be Observer. The parameter can be changed later by changing the
max_access_levelattribute.port (
Optional[int]) – The port to connect to. If None, and ssl is None, then 7443 will be tried with SSL, and if it fails, then 7000 will be tried without SSL.ssl (
Optional[bool]) – Whether or not to use SSL. If None, then SSL will be chosen based on the port number.client_certificate_path (
Optional[str]) – Path to a PEM file containing the client certificate for TLS client authentication. The file may also contain the private key, or it can be provided separately via client_key_path.client_key_path (
Optional[str]) – Path to a PEM file containing the client private key for TLS client authentication. Only needed if the key is not included in client_certificate_path.server_ca_file (
Optional[str]) – Path to a PEM file containing CA certificate(s) for verifying the server’s certificate. If not provided, server certificate verification is disabled (default).tls_server_name (
Optional[str]) – Expected server name for TLS hostname verification. If server_ca_file is provided but tls_server_name is None, certificate chain verification is performed but hostname is not checked. This is useful when connecting through tunnels or port forwards where the connection hostname differs from the certificate’s CN/SAN.
- property access_level: AccessLevel¶
- property block: tuple[bool, float]¶
Returns whether the block is currently temperature-controlled, and the current block temperature setting.
- compile_eds(run_name)[source]¶
Take a finished run directory in experiments:, compile it into an EDS, and move it to public_run_complete:
- Return type:
- property connected: bool¶
Whether or not there is a current connection to the machine.
Note that when using automatic connections, this will usually be False, because connections will only be active when running a command.
- property connection: QSConnection¶
The
QSConnectionfor the connection, or aConnectionError.
- cover_lower(check=True, ensure_drawer=True)[source]¶
Lower/engage the plate cover, closing the drawer if needed.
- Return type:
- property cover_position: Literal['Up', 'Down', 'Unknown', '']¶
Return the cover position from the ENG? command. Note that this does not always seem to work.
- define_protocol(protocol)[source]¶
Send a protocol to the machine. This is not related to a particular experiment. The name on the machine is set by the protocol.
- drawer_close(lower_cover=True, check=True)[source]¶
Close the machine drawer using the OPEN command. This will ensure proper cover/drawer operation. It will not check run status, and will open and close the drawer during runs and potentially during imaging.
By default, it will lower the cover automaticaly after closing, use lower_cover=False to not do so.
- Return type:
- drawer_open()[source]¶
Open the machine drawer using the OPEN command. This will ensure proper cover/drawer operation. It will not check run status, and will open and close the drawer during runs and potentially during imaging.
- Return type:
- property drawer_position: Literal['Open', 'Closed', 'Unknown']¶
Return the drawer position from the DRAW? command.
- generate_random_key()[source]¶
Generate a 6-digit random authentication key on the server.
Requires Controller or higher access. The key is valid for 10 minutes and grants Administrator access when used with
authenticate. Only one key is active at a time; calling this again before the key expires returns the same key.- Return type:
- Returns:
A 6-digit string (e.g., “042371”).
- get_all_filterdata(run=None, as_list=False)[source]¶
Fetch all filterdata from the machine.
Returns a list of Rust PlateData objects (as_list=True) or a Polars DataFrame.
- Return type:
- get_filterdata_one(ref, *, run=None, return_files=False)[source]¶
Fetch a single filterdata reading from the machine.
Returns a Rust PlateData object with timestamp set from quant data.
- Return type:
- get_zone_count()[source]¶
Query the number of temperature control zones from the server.
- Return type:
- Returns:
The number of zones (typically 6 for current QuantStudio instruments).
- list_files(path, *, leaf='FILE', verbose=False, recursive=False)[source]¶
- Return type:
list[str] |list[FileListInfo]
- property max_access_level: AccessLevel¶
- property power: bool¶
Get and set the machine’s operational power (lamp, etc) as a bool.
Setting this to False will not turn off the machine, just power down the lamp, temperature control, etc. It will do so even if there is currently a run.
- read_dir_as_zip(path, leaf='FILE')[source]¶
Read a directory on the
- Parameters:
- Returns:
the returned zip file
- Return type:
- restart_system()[source]¶
Restart the system (both the InstrumentServer and android interface) by killing the zygote process.
- Return type:
- run_command(command)[source]¶
Run a SCPI command, and return the response as a string. Waits for OK, not just NEXT.
- Parameters:
command (str) – command to run
- Returns:
Response message (after “OK”, not including it)
- Return type:
- Raises:
CommandError – Received an Error response.
- run_command_bytes(command)[source]¶
Run an SCPI command, and return the response as bytes (undecoded). Returns after the command is processed (OK or NEXT), but potentially before it has completed (NEXT).
- Parameters:
command (
str|bytes|SCPICommand) – command to run- Returns:
Response message (after “OK” or “NEXT”, likely “” in latter case)
- Return type:
- Raises:
CommandError – Received
- run_command_to_ack(command)[source]¶
Run an SCPI command, and return the response as a string. Returns after the command is processed (OK or NEXT), but potentially before it has completed (NEXT).
- Parameters:
commands – command to run
- Returns:
Response message (after “OK” or “NEXT”, likely “” in latter case)
- Return type:
- Raises:
CommandError – Received an Error response.
- run_command_to_bytes(command)[source]¶
Run an SCPI command, and return the response as bytes (undecoded). Waits for NEXT.
- Return type:
- save_run_from_storage(machine_path, download_path, overwrite=False)[source]¶
Download a file from run storage on the machine.
- set_status_led(color, mode='on')[source]¶
Set the front-panel status LED.
This is the machine’s indicator light, not the optical excitation lamp.
- Parameters:
color (
StatusLedColor|str) – One of red, green, blue, yellow, cyan, magenta, white (aStatusLedColoror its name, case-insensitive).mode (
StatusLedMode|str) – “on” (solid, the default), “blink”, or “off” (aStatusLedModeor its name).
- Return type:
Notes
Requires Controller access.
- property status_led: StatusLedState¶
Current color and mode of the front-panel status LED.
Reading returns a
StatusLedState(.colorisNonewhen off). Setting accepts a color name/StatusLedColor(solid on), or a(color, mode)tuple.
qslib.plate_setup module¶
Code for handling plate setup.
- class qslib.plate_setup.PlateSetup(sample_wells=None, samples=(), plate_type=96)[source]¶
Bases:
object- classmethod from_array(array)[source]¶
Given an (8,12) or (16,24) array of sample names, create a PlateSetup. Interprets None, “None”, and “null” as empty wells.
- Return type:
- classmethod from_picklist(picklist, plate_name=None, labware=None)[source]¶
Create a PlateSetup from a Kithairon PickList.
- Parameters:
picklist (PickList or str) – The picklist to read. If a string, it is treated as a path to a CSV picklist.
plate_name (str or None) – The destination plate that the PlateSetup is for. If None, and there is only one destination plate, that one is used. If there are multiple destination plates, the user must specify one.
labware (Labware or None) – The Kithairon labware to use. If None, the default labware is used.
- Raises:
ValueError – If: - There is more than one destination plate and no plate_name is specified. - There are multiple sample names in a single well. - The destination plate is not a destination plate type in the Labware. - The destination plate shape is not 96 or 384 (taken from Labware)
- Return type:
Self
- classmethod from_xml_string(xml)[source]¶
Create a PlateSetup from an XML string (or bytes).
Uses Rust XML parsing internally.
- Return type:
- get_wells(samples_or_wells)[source]¶
Given a sample, well, or list of the two, returns the corresponding wells. Note that this relies on samples not having well-like names.
- property sample_wells¶
- to_xml_string(existing_xml=None)[source]¶
Serialize this PlateSetup to an XML string.
If existing_xml is provided, the existing XML structure is preserved and only the sample data is updated. Otherwise a new XML structure is created.
Uses Rust XML handling internally.
- Return type:
- property well_samples: Series¶
qslib.processors module¶
Fluorescence data processors supporting both Polars and Pandas DataFrames.
This module provides processor classes that can work with either Polars or Pandas data without requiring the user to choose. The process() method automatically detects the input type and applies the appropriate implementation.
- class qslib.processors.NormRaw[source]¶
Bases:
ProcessorA Processor that takes no arguments and passes through raw fluorescence values.
- class qslib.processors.NormToMaxPerWell(stage=None, step=None, cycle=None, point=None, *, expr=None, selection=None)[source]¶
Bases:
ProcessorA Processor that divides the fluorescence reading for each (filterset, well) pair by the max value of that pair within a particular selection of data.
See NormToMeanPerWell for usage examples.
- class qslib.processors.NormToMeanPerWell(stage=None, step=None, cycle=None, point=None, *, expr=None, selection=None)[source]¶
Bases:
ProcessorA Processor that divides the fluorescence reading for each (filterset, well) pair by the mean value of that pair within a particular selection of data.
The easiest way to use this is to give a particular stage (all data in that stage will be used), or a stage and set of cycles (those cycles in that stage will be used). For example:
To normalize to the mean stage 8 values, use NormToMeanPerWell(stage=8).
- To normalize to the first 5 cycles of stage 2, use
NormToMeanPerWell(stage=2, cycle=range(1, 6)).
For Polars, use expr for custom filter expressions. For Pandas, use selection for arbitrary indexing.
- class qslib.processors.Processor[source]¶
Bases:
objectBase class for fluorescence data processors.
Processors transform fluorescence data (normalization, smoothing, etc.) and work with both Polars and Pandas DataFrames automatically. The process() method detects the input type and applies the appropriate implementation.
For Pandas, there’s also process_scoped() for scope-aware processing.
- process(data)[source]¶
Process the data, auto-detecting whether it’s Polars or Pandas.
- Parameters:
data (pl.LazyFrame, pl.DataFrame, or pd.DataFrame) – The fluorescence data to process.
- Returns:
The processed data.
- Return type:
Same type as input
- process_scoped(data, scope)[source]¶
Process Pandas data only if scope matches this processor’s scope.
This is useful for writing scope-agnostic code, provided that you call this for every scope before using the data.
- Parameters:
data (pd.DataFrame) – The fluorescence data to process.
scope ("all" or "limited") –
“all”: the entire welldata array.
”limited”: all time points, but limited to the filter sets and samples being plotted.
- Returns:
The processed data (or unchanged if scope doesn’t match).
- Return type:
pd.DataFrame
- class qslib.processors.SmoothEMWMean(com=None, span=None, halflife=None, alpha=None, min_periods=0, adjust=True, ignore_na=False)[source]¶
Bases:
ProcessorA Processor that smooths fluorescence readings using an exponentially weighted moving average (EWMA).
- class qslib.processors.SmoothWindowMean(window, min_periods=None, center=False, win_type=None, closed=None)[source]¶
Bases:
ProcessorA Processor that smooths fluorescence readings using a rolling window mean.
- class qslib.processors.SubtractByMeanPerWell(stage=None, step=None, cycle=None, point=None, *, expr=None, selection=None)[source]¶
Bases:
ProcessorA Processor that subtracts the fluorescence reading for each (filterset, well) pair by the mean value of that pair within a particular selection of data.
See NormToMeanPerWell for usage examples.
- qslib.processors.match_expr(stage=None, cycle=None, step=None, point=None, expr=None)[source]¶
Build a Polars filter expression from stage/cycle/step/point constraints.
- Return type:
Expr
- qslib.processors.match_expr_single(stage=None, cycle=None, step=None, point=None)[source]¶
Build a Polars filter expression for single values.
- Return type:
Expr
- qslib.processors.norm_zero_to_one_per_well(zero_filter, one_filter)[source]¶
Create a Polars expression that normalizes fluorescence to a 0-1 range.
- Parameters:
zero_filter (FilterDict) – Filter for data points to use as the “zero” baseline.
one_filter (FilterDict) – Filter for data points to use as the “one” level.
- Returns:
Expression that computes normalized fluorescence.
- Return type:
pl.Expr
- qslib.processors.pandas_process(data, processors, scope='limited', ylabel=None)[source]¶
Apply processors to Pandas data.
- Parameters:
- Returns:
Processed data, optionally with updated ylabel.
- Return type:
pd.DataFrame or (pd.DataFrame, str)
qslib.protocol module¶
- class qslib.protocol.CustomStep(body, identifier=None, repeat=1)[source]¶
Bases:
ProtoCommandA protocol step composed of SCPI/protocol commands.
- property body: list[ProtoCommand]¶
- class qslib.protocol.Exposure(settings, state='HoldAndCollect')[source]¶
Bases:
ProtoCommandModifies exposure settings.
- class qslib.protocol.HACFILT(filters, default_filters=NOTHING)[source]¶
Bases:
ProtoCommandSets filters for
HoldAndCollect.
- class qslib.protocol.Hold(time, increment=<Quantity(0, 'second')>, incrementcycle=2, incrementstep=2)[source]¶
Bases:
ProtoCommandA protocol hold (for a time) command.
-
increment:
Quantity¶
-
increment:
- class qslib.protocol.HoldAndCollect(time, increment=<Quantity(0, 'second')>, incrementcycle=2, incrementstep=2, tiff=False, quant=True, pcr=False)[source]¶
Bases:
ProtoCommandA protocol hold (for a time) and collect (set by HACFILT) command.
-
increment:
Quantity¶
-
time:
Quantity¶
-
increment:
- qslib.protocol.NZONES: int = 6¶
Default number of temperature control zones.
Current QuantStudio instruments have 6 zones. This is used when expanding a single temperature to a per-zone list. Query the actual count from the server with
Machine.get_zone_count()(sendsTBC:ControlZones?).
- class qslib.protocol.ProtoCommand(*args, **kwargs)[source]¶
Bases:
ABC
- class qslib.protocol.Protocol(stages=NOTHING, name=NOTHING, volume=50.0, runmode='standard', filters=NOTHING, covertemperature=105.0, prerun=NOTHING, postrun=NOTHING, classname='Protocol')[source]¶
Bases:
ProtoCommandA run protocol for the QuantStudio. Protocols encapsulate the temperature and camera controls for an entire run. They are composed of
Stage`s, which may repeat for a number of cycles, and the stages are in turn composed of Steps, which may be created for usual cases with :class:`Step, or from SCPI commands. Steps may repeat their contents as well, but this is not yet implemeted.- Parameters:
stages (Iterable[Stage]) – The stages of the protocol, likely
Stage.stage (_NumOrRefIndexer[Stage]) – A more convenient way of accessing the stages of the protocol, with numbering that matches the machine.
name (str | None) – A protocol name. If not set, a timestamp will be used, unlike AB’s uuid.
volume (float) – The sample volume, in µL.
runmode (str | None) – The run mode.
covertemperature (float (default 105.0)) – The cover temperature
filters (Sequence[str]) – A list of default filters that can be used by any collection commands that don’t specify their own.
prerun (Sequence[SCPICommand]) – Sets PRERUN. DO NOT USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.
postrun (Sequence[SCPICommand]) – Sets POSTRUN. DO NOT USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.
Notes
Protocol equality is based on functional attributes (stages, volume, runmode, filters, covertemperature, prerun, postrun) but excludes the name. This means two protocols with identical configurations but different names are considered equal.
- property all_filters: Collection[FilterSet]¶
A list of all filters used at some point in the protocol.
- property all_points: DataFrame¶
- check_compatible(new, status)[source]¶
Checks compatibility for changing a running protocol to a new one.
Raises ValueError if incompatible, returns True if compatible.
- Parameters:
- Raises:
ValueError – Protocols are incompatible.
- Return type:
- property dataframe: DataFrame¶
A DataFrame of the temperature protocol.
- classmethod from_scpi_string(text)[source]¶
Parse a Protocol from an SCPI command string.
- Return type:
-
postrun:
Sequence[SCPICommandLike]¶
-
prerun:
Sequence[SCPICommandLike]¶
- property stage: _NumOrRefIndexer[Stage]¶
A more convenient view of
Protocol.stages. This allows one-indexed access, such that protocol.stage[5] == protocol.stages[6] is stage 5 of the protocol, in the interpretation of tha machine. Indexing can use slices, and is inclusive, so protocol.stage[5:6] returns stages 5 and 6. Getting, setting, and appending stages are all supported through this interface.
- to_scpi_string_rust()[source]¶
Serialize this protocol to an SCPI string using the Rust implementation.
- Return type:
- class qslib.protocol.Ramp(temperature, increment=<Quantity(0.0, 'delta_degree_Celsius')>, incrementcycle=2, incrementstep=2, rate=100.0, cover=None)[source]¶
Bases:
ProtoCommandRamps temperature to a new setting.
-
increment:
Quantity¶
-
temperature:
Quantity¶
-
increment:
- class qslib.protocol.Stage(steps, repeat=1, index=None, label=None, default_filters=())[source]¶
Bases:
ProtoCommandA Stage in a protocol, composed of
Steps with a possible repeat.- dataframe(start_time=0, previous_temperatures=None)[source]¶
Create a dataframe of the steps in this stage.
- Parameters:
start_time (
float) – The initial start time, in seconds, of the stage (before the ramp to the first step). Default is 0.previous_temperatures (
Optional[list[float]]) – A list of temperatures at the end of the previous stage, to allow calculation of ramp time. If None, the ramp is assumed to take no time.
- Return type:
DataFrame
- classmethod hold_at(temperature, total_time, step_time=None, collect=None, filters=())[source]¶
Hold at a temperature for a set amount of time, with steps of a configurable fixed time.
- Parameters:
temperatures – The temperature or temperatures to hold. If not strings or quantities, the value/values are interpreted as °C.
total_time (
int|str|Quantity) – Desired total time for the stage. If this is not a multiple of step_time, it may not be the actual total time for the stage. The function will emit a warning if the difference is more than 10%. If an integer, value is interpreted as seconds.step_time (
Union[int,str,Quantity,None]) – If None (default), the stage will have one step. Otherwise, it will have steps of this time. If an integer, value is interpreted as seconds.collect (
Optional[bool]) – Whether or not each step should collect fluorescence data. If None (default), collects data if filters is explicitly set.filters (
Sequence[str|FilterSet]) – A list of filters to collect. If empty, and collect is True, then each step will collect the default filters for theProtocol.
- Returns:
The resulting Stage
- Return type:
- Raises:
ValueError – If step time is larger than total time.
- classmethod hold_for(temperature, total_time, step_time=None, collect=None, filters=())¶
Hold at a temperature for a set amount of time, with steps of a configurable fixed time.
- Parameters:
temperatures – The temperature or temperatures to hold. If not strings or quantities, the value/values are interpreted as °C.
total_time (
int|str|Quantity) – Desired total time for the stage. If this is not a multiple of step_time, it may not be the actual total time for the stage. The function will emit a warning if the difference is more than 10%. If an integer, value is interpreted as seconds.step_time (
Union[int,str,Quantity,None]) – If None (default), the stage will have one step. Otherwise, it will have steps of this time. If an integer, value is interpreted as seconds.collect (
Optional[bool]) – Whether or not each step should collect fluorescence data. If None (default), collects data if filters is explicitly set.filters (
Sequence[str|FilterSet]) – A list of filters to collect. If empty, and collect is True, then each step will collect the default filters for theProtocol.
- Returns:
The resulting Stage
- Return type:
- Raises:
ValueError – If step time is larger than total time.
- property step: _NumOrRefIndexer[CustomStep]¶
- classmethod stepped_ramp(from_temperature, to_temperature, total_time, *, n_steps=None, temperature_step=None, points_per_step=1, collect=None, filters=(), start_increment=False)[source]¶
Hold at a series of temperatures, from one to another.
- Parameters:
from_temperature (
Union[float,str,Quantity,Sequence[float]]) – Initial temperature/s (inclusive). If None, uses the final temperature of the previous stage (FIXME: None is not currently handled).to_temperature (
Union[float,str,Quantity,Sequence[float]]) – Final temperature/s (inclusive).total_time (
int|str|Quantity) – Total time for the stagen_steps (
Optional[int]) – Number of steps. If None, uses 1.0 Δ°C steps, or, if doing a multi-temperature change, uses maximum step of 1.0 Δ°C. If n_steps is specified, it is the number of temperature steps to take. Normally, since there is an initial cycle of the starting temperatures, this means there will be n_steps + 1 cycles. If start_increment is True, and the initial cycle is already stepped away from the starting temperature, then there will be only n_steps cycles.temperature_step (
Union[float,str,Quantity,None]) – Step temperature change (optional). Must be None, or correctly match calculation, if n_steps is not None. If both this and n_steps are None, default is 1.0 Δ°C steps. If temperature step does not exactly fit range, it will be adjusted, with a warning if the change is more than 5%. Sign is ignored. If doing a multi-temperature change, then this is the maximum temperature step.collect (
Optional[bool]) – Collect data? If None, collects data if filters is set explicitly.start_increment (
bool) – If False (default), start at the from_temperature, holding there for the same hold time as every other temperature. If True, start one step away from the from_temperature. This is useful, for example, if the previous stage held at a particular temperature, and you now want to step away from that temperature. When True, note the remarks about n_steps above.
- Returns:
The resulting stage.
- Return type:
-
steps:
Sequence[CustomStep]¶
- class qslib.protocol.Step(time, temperature, collect=None, temp_increment=<Quantity(0.0, 'delta_degree_Celsius')>, temp_incrementcycle=2, temp_incrementpoint=None, time_increment=<Quantity(0, 'second')>, time_incrementcycle=2, time_incrementpoint=None, filters=(), pcr=False, quant=True, tiff=False, repeat=1, default_filters=())[source]¶
Bases:
CustomStepA normal protocol step, of a hold and possible collection.
- Parameters:
time (int) – The step time setting, in seconds.
temperature (float | Sequence[float]) – The temperature hold setting, either as a float (all zones the same) or a sequence (of correct length) of floats setting the temperature for each zone.
collect (
Optional[bool]) – Collect fluorescence data? If None (default), collect only if the Step has an explicit filters setting.temp_increment (float) – Amount to increment all zone temperatures per cycle on and after
temp_incrementcycle.temp_incrementcycle (int (default 2)) – First cycle to start the increment changes. Note that the default in QSLib is 2, not 1 (as in AB’s software), so that leaving this alone makes sense (the first cycle will be at
temperature, the next attemperature + temp_incrementcycle.time_increment (float)
time_incrementcycle (int) – The same settings for time per cycle.
filters (Sequence[FilterSet | str] (default empty)) – A list of filter pairs to collect, either using
FilterSetor a string like “x1-m4”. If collect is True and this is empty, then the filters will be set by the Protocol.
Notes
This currently does not support step-level repeats, which do exist on the machine.
- property body: list[ProtoCommand]¶
- duration_at_cycle_point(cycle, point=1)[source]¶
Durations of the step at cycle (from 1)
- Return type:
Quantity
- durations_at_cycle(cycle)[source]¶
Duration of the step (excluding ramp) at cycle (from 1)
- Return type:
list[Quantity]
-
temp_increment:
Quantity¶
-
temperature:
Quantity¶
- property temperature_list: Quantity¶
- temperatures_at_cycle(cycle)[source]¶
Temperatures of the step at cycle (from 1)
- Return type:
list[Quantity]
- temperatures_at_cycle_point(cycle, point)[source]¶
Temperatures of the step at cycle (from 1)
- Return type:
Quantity
-
time:
Quantity¶
-
time_increment:
Quantity¶
qslib.scpi_commands module¶
SCPI Command class and parsing
- exception qslib.scpi_commands.AccessGiven[source]¶
Bases:
CommandErrorRaised when access has already been given to another session.
- exception qslib.scpi_commands.AccessLevelExceeded[source]¶
Bases:
CommandErrorRaised when the requested access level exceeds what is allowed.
- class qslib.scpi_commands.ArgList(opts, args)[source]¶
Bases:
objectA representation of an SCPI list of options (-key=value) and arguments.
- exception qslib.scpi_commands.AuthError[source]¶
Bases:
CommandErrorRaised when authentication fails (wrong password).
- exception qslib.scpi_commands.ExclusiveAccessGiven[source]¶
Bases:
CommandErrorRaised when another session holds exclusive access.
- exception qslib.scpi_commands.InsufficientAccess[source]¶
Bases:
CommandErrorRaised when the current access level is insufficient for an operation.
- exception qslib.scpi_commands.NoMatch[source]¶
Bases:
CommandErrorRaised when a file or pattern match finds no results.
- class qslib.scpi_commands.SCPICommand(command, *args, comment=None, **kwargs)[source]¶
Bases:
SCPICommandLikeA representation of an SCPI Command.
-
args:
Sequence[Union[str,int,float,number[Any],Sequence[str|int|float|number[Any]],Sequence[SCPICommand]]]¶
- classmethod from_scpicommand(com)[source]¶
Try to create the object from an
SCPICommand.- Return type:
- classmethod from_string(command_string)[source]¶
Parse (as SCPICommands) an SCPI command string.
- Return type:
- specialize()[source]¶
If possible, convert SCPICommand to QSLib classes for the command.
- Return type:
- to_scpicommand(**kwargs)[source]¶
Convert the object to an
SCPICommand- Return type:
-
args:
- class qslib.scpi_commands.SCPICommandLike[source]¶
Bases:
ABCAbstract class for an object that can be converted from/to an SCPICommand.
- abstract classmethod from_scpicommand(com)[source]¶
Try to create the object from an
SCPICommand.- Return type:
TypeVar(T)
- abstract to_scpicommand(**kwargs)[source]¶
Convert the object to an
SCPICommand- Return type:
- qslib.scpi_commands.quote_string_if_needed(s)[source]¶
Quote a string if it contains spaces, quotes, or newlines.
Strings with newlines are wrapped in <quote>…</quote> tags. Strings with spaces or quotation marks are wrapped in double quotes with escaped quotes. Other characters like $, {, } are not escaped.
- Return type:
qslib.version module¶
Module contents¶
- class qslib.AccessLevel(value)¶
Bases:
object- Administrator = AccessLevel.Administrator¶
- Controller = AccessLevel.Controller¶
- Full = AccessLevel.Full¶
- Guest = AccessLevel.Guest¶
- Observer = AccessLevel.Observer¶
- value¶
- exception qslib.CommandError¶
Bases:
CommandResponseError
- class qslib.CustomStep(body, identifier=None, repeat=1)[source]¶
Bases:
ProtoCommandA protocol step composed of SCPI/protocol commands.
- property body: list[ProtoCommand]¶
- class qslib.Experiment(name=None, protocol=None, plate_setup=None, _create_xml=True)[source]¶
Bases:
objectA QuantStudio experiment / EDS file
This class can create, modify, load and save experiments in several ways, run them, and control and modify them while running.
Experiments can be loaded from a file:
>>> exp: Experiment = Experiment.from_file("experiment.eds")
They can also be loaded from a running experiment:
>>> machine = Machine("localhost", password="password") >>> exp = Experiment.from_running(machine)
Or from the machine’s storage:
>>> exp = Experiment.from_machine(machine, "experiment")
They can also be created from scratch:
>>> exp = Experiment("an-experiment-name") >>> exp.protocol = Protocol([Stage([Step(time=60, temperature=60)])]) >>> exp.plate_setup = PlateSetup({"sample_name": "A5"})
And they can be run on a machine:
>>> exp.run(machine)
Data can be accessed in a few ways:
The (hopefully) easiest way is with welldata, which has multi-indexes for both rows and columns.
>>> exp.welldata.loc[('x1-m4', 4), [('time', 'hours'), ('A05', 'fl')]].plot()
Or for a temperature curve:
>>> exp.welldata.loc[('x1-m4', 4), [('A05', 'st'), ('A05', 'fl')]].plot()
filterdata should still work normally.
Notes
There are a few differences in how QSLib and AB’s software handles experiments.
AB’s software considers the run as starting when the machine indicates “Run Starting”. This is stored as
runstarttimein QSLib, but as it may include the lamp warmup (3 minutes) and other pre-actual-protocol time, QSLib instead prefersactivestarttime, which it sets from the beginning of the first real (not PRERUN) Stage, at which point the machine starts its own active clock and starts ramping to the first temperature. QSLib uses this as the start time reference in its data, and also includes the timestamp from the machine.The machine has a specific language for run protocols. QSLib uses this language. AB’s Design and Analysis software does not, instead using an XML format. Not everything in the machine’s language is possible to express in the XML format (eg, disabling pcr analysis, saving images); the XML format has some concepts not present in the machine format, and is generally more complicated and harder to understand. QSLib uses and trusts the machine’s protocol if at all possible, even for files written by AB D&A (it is stored in the log if the run has started).
QSLib will try to write a reasonable XML protocol for AB D&A to see, but it may by an approximation or simply wrong, if the actual protocol can’t be expressed there. It will also store the actual protocol in tcprotocol.xml, and its own representation.
By default, creating a step with a per-cycle increment in QSLib starts the change on cycle 2, not cycle 1, as is the default in the software.
Immediate pause/resume, mid-run stage addition, and other functions are not supported by AB D&A and experiments using them may confuse the software later.
QSLib writes notes to XML files, and tries to create reasonable XML files for AB D&A, but may still cause problems. At the moment, it makes clear that its files are its own (setting software versions in experiment.xml and Manifest.mf).
- abort(machine=None)[source]¶
If this experiment is running, abort it, stopping it immediately.
Requires and takes exclusive Controller access on the machine.
- Raises:
NotRunningError – the experiment is not currently running
- Return type:
-
activeendtime:
datetime|None¶ The actual end of the main part of the run, indicated by “Stage POSTRun” or an abort.
-
activestarttime:
datetime|None¶ The actual beginning of the first stage of the run, defined as the first “Run Stage” message in the log after “Stage PRERUN”. This is not what AB’s software considers the start of a run.
- property all_filters: Collection[FilterSet]¶
All filters used at some point in the experiment.
If the experiment has data, this is based on the existing data. Otherwise, it is based on the experiment protocol.
- property amplification_data: DataFrame¶
- property analysis_result: DataFrame¶
- property calibrations: dict¶
Calibration data parsed from the EDS calibrations directory.
Returns a dict with keys ‘uniformity’, ‘background’, and optionally ‘puredye’.
- change_protocol(new_protocol, machine=None, force=False)[source]¶
For a running experiment and an updated protocol, check compatibility with the current run, and if possible, update the protocol in the experiment file and on the machine, changing the current run.
Changes that should be possible:
Changing the number of cycles of the current run to a higher or lower value (but higher or equal to the current cycle number), allowing stages to be lengthened, shortened, or stopped.
Adding new stages after the current stage.
Arbitrarily changing any stage that hasn’t started.
For safest results, ensure power saving is turned off in the Android software.
- change_protocol_from_now(new_stages, machine=None)[source]¶
- Return type:
For a running experiment, change the remaining stages to be the provided :param:`new_stages` list. This is a convenience function that:
Gets the currently-running stage and cycle.
Sets the repeat number of the current stage to its current cycle, thus ending it after the end of the current cycle.
Changes the remainder of the stages to be those in the :param:`new_stages` list.
Because this does not impact any current or past stages, there is less of a need to ensure that the stages provided are compatible with the old protocol. The only check done is to ensure that, if the provided stages have any collection commands using default filters, the old protocol has specified default filters. This function does not allow the default filters to be changed: if you want to use filters other than the defaults, or defaults were not provided in the old protocol, then either specify filters explicitly (recommended) for new stages you’d like to be different, or use
Experiment.change_protocoldirectly.
- data_for_sample(sample)[source]¶
Convenience function to return data for a specific sample.
Finds wells using
self.plate_setup.sample_wells[sample], then returnsself.welldata.loc[:, wells]- Parameters:
sample (str) – sample name
- Returns:
Slice of welldata. Will have multiple wells if sample is in multiple wells.
- Return type:
pd.Dataframe
- property events: DataFrame¶
- property filter_data: DataFrame¶
- property filter_data_polars: DataFrame¶
- property filter_strings: list[str]¶
All filters, as x?-m? strings, used at some point in the experiment.
- classmethod from_file(file)[source]¶
Load an experiment from an EDS file.
- Returns:
file – The filename or file handle to read.
- Return type:
str or os.PathLike[str] or IO[bytes]
- Raises:
ValueError – if the file does not appear to be an EDS file (lacks an experiment.xml).
- classmethod from_machine(machine, name)[source]¶
Create an experiment from data on a machine, checking the running experiment if any, the machine’s public_run_complete storage, and the machine’s uncollected storage.
- Parameters:
- Returns:
a copy of the experiment
- Return type:
- classmethod from_machine_storage(machine, name)[source]¶
Create an experiment from the machine’s storage.
- Parameters:
- Returns:
a copy of the experiment
- Return type:
- classmethod from_running(machine)[source]¶
Create an experiment from the one currently running on a machine.
- Parameters:
machine (Machine) – the machine to connect to
- Returns:
a copy of the running experiment
- Return type:
- classmethod from_uncollected(machine, name, move=False)[source]¶
Create an experiment from the uncollected (not yet compressed) storage.
- Parameters:
- Returns:
a copy of the experiment
- Return type:
- get_status(machine=None)[source]¶
Return the status of the experiment, if currently running.
Requires Observer access on the machine.
- Raises:
NotRunningError – the experiment is not currently running
- Return type:
- info(format='markdown', plate='list')[source]¶
Generate a summary of the experiment, with some formatting configuation. str() uses this with default parameters.
- Parameters:
format ("markdown" or "org", optional) – Format of output, currently “markdown” or “org”, and currently matters only when plate is “table”. By default “markdown”. If an unknown value, passed as tablefmt to tabulate.
plate ("list" or "table", optional) – Format of plate information. “list” gives a list of samples, “table” outputs a plate layout table (possibly quite wide). By default “list”.
- Returns:
Summary
- Return type:
- info_html()[source]¶
Create a self-contained HTML summary (returned as a string, but very large) of the experiment.
- Return type:
- property multicomponent_data: DataFrame¶
- pause_now(machine=None)[source]¶
If this experiment is running, pause it (immediately).
Requires and takes exclusive Controller access on the machine.
- Raises:
NotRunningError – the experiment is not currently running
- Return type:
-
plate_setup:
PlateSetup¶ Plate setup for the experiment.
- plot_anneal_melt(samples=None, filters=None, anneal_stages=None, melt_stages=None, between_stages=None, process=None, normalization=None, ax=None, marker=None, legend=True, figure_kw=None, line_kw=None)[source]¶
Plots anneal/melt curves.
This uses solid lines for the anneal, dashed lines for the melt, and dotted lines for anything “between” the anneal and melt (for example, a temperature hold).
Line labels are intended to provide full information when read in combination with the axes title. They will only include information that does not apply to all lines. For example, if every line is from the same filter set, but different samples, then only the sample will be shown. If every line is from the same sample, but different filter sets, then only the filter set will be shown. Wells are shown if a sample has multiple wells.
- Parameters:
samples (
Union[str,Sequence[str],None]) – A reference to a single sample (a string), a list of sample names, or a Python regular expression as a string, matching sample names (full start-to-end matches only). Well names may also be included, in which case each well will be treated without regard to the sample name that may refer to it. Note this means you cannot give your samples names that correspond with well references. If not provided, all (named) samples will be included.filters (
Union[str,FilterSet,Collection[str|FilterSet],None]) – Optional. A filterset (string or FilterSet) or list of filtersets to include in the plot. Multiple filtersets will be plotted on the same axes. Optional; if None, then all filtersets with data in the experiment will be included.anneal_stages (int | Sequence[int] | None) – Optional. A stage or list of stages (integers, starting from 1), corresponding to the anneal, melt, and stages between the anneal and melt (if any). Any of these may be None, in which case the function will try to determine the correct values automatically.
melt_stages (int | Sequence[int] | None) – Optional. A stage or list of stages (integers, starting from 1), corresponding to the anneal, melt, and stages between the anneal and melt (if any). Any of these may be None, in which case the function will try to determine the correct values automatically.
between_stages (int | Sequence[int] | None) – Optional. A stage or list of stages (integers, starting from 1), corresponding to the anneal, melt, and stages between the anneal and melt (if any). Any of these may be None, in which case the function will try to determine the correct values automatically.
normalization (
Optional[Processor]) – Optional. A Normalizer instance to apply to the data. By default, this is NormRaw, which passes through raw fluorescence values. NormToMeanPerWell also works well.ax (
Optional[Axes]) – Optional. An axes to put the plot on. If not provided, the function will create a new figure, by default with constrained_layout=True, though this can be modified with figure_kw.marker (
Optional[str]) – The marker format for data points, or None for no markers (default).legend (
Union[bool,Literal['inset','right']]) – Whether to add a legend. True (default) decides whether to have the legend as an inset or to the right of the axes based on the number of lines. “inset” and “right” specify the positioning. Note that for “right”, you must use some method to adjust the axes positioning: constrained_layout, tight_layout, or manually reducing the axes width are all options.figure_kw (
Optional[dict[str,Any]]) – Optional. A dictionary of options passed through as keyword options to the figure creation. Only applies if ax is None.line_kw (
Optional[dict[str,Any]]) – Optional. A dictionary of keywords passed to all three plotting commands.
- Return type:
- Returns:
Axes – The axes object of the plot.
- plot_over_time(samples=None, filters=None, stages=slice(None, None, None), process=None, normalization=None, ax=None, legend=True, temperatures='axes', marker=None, stage_lines=True, annotate_stage_lines=True, annotate_events=True, figure_kw=None, line_kw=None, time_units='h')[source]¶
Plots fluorescence over time, optionally with temperatures over time.
Line labels are intended to provide full information when read in combination with the axes title. They will only include information that does not apply to all lines. For example, if every line is from the same filter set, but different samples, then only the sample will be shown. If every line is from the same sample, but different filter sets, then only the filter set will be shown. Wells are shown if a sample has multiple wells.
- Parameters:
samples (str | Sequence[str] | None) – A reference to a single sample (a string), a list of sample names, or a Python regular expression as a string, matching sample names (full start-to-end matches only). Well names may also be included, in which case each well will be treated without regard to the sample name that may refer to it. Note this means you cannot give your samples names that correspond with well references. If not provided, all (named) samples will be included.
filters (str | FilterSet | Collection[str | FilterSet] | None) – Optional. A filterset (string or FilterSet) or list of filtersets to include in the plot. Multiple filtersets will be plotted on the same axes. Optional; if None, then all filtersets with data in the experiment will be included.
stages (slice | int | Sequence[int]) – Optional. A stage, list of stages, or slice (all using integers starting from 1), to include in the plot. By default, all stages are plotted. For example, to plot stage 2, use stages=2; to plot stages 2 and 4, use stages=[2, 4], to plot stages 3 through 15, use stages=slice(3, 16) (Python ranges are exclusive on the end). Note that is a slice, you can use None instead of a number to denote the beginning/end.
normalization (PolarsProcessor | None) – Optional. A Normalizer instance to apply to the data. By default, this is NormRaw, which passes through raw fluorescence values. NormToMeanPerWell also works well.
temperatures (Literal[False, ‘axes’, ‘inset’, ‘twin’]) –
Optional (default “axes”). Several alternatives for displaying temperatures. “axes” uses a separate axes (created if ax is not provided, otherwise ax must be a list of two axes).
Temperatures are from Experiment.temperature, and are thus the temperatures as recorded during the run, not the set temperatures. Note that this has a very large number of data points, something that should be dealt with at some point.
ax (Axes’ | ‘Sequence[Axes]’ | None) – Optional. An axes to put the plot on. If not provided, the function will create a new figure, by default with constrained_layout=True, though this can be modified with figure_kw. If temperatures=”axes”, you must provide a list or tuple of two axes, the first for fluorescence, the second for temperature.
marker (str | None) – The marker format for data points, or None for no markers (default).
legend (bool | Literal[‘inset’, ‘right’]) – Whether to add a legend. True (default) decides whether to have the legend as an inset or to the right of the axes based on the number of lines. “inset” and “right” specify the positioning. Note that for “right”, you must use some method to adjust the axes positioning: constrained_layout, tight_layout, or manually reducing the axes width are all options.
stage_lines (bool | Literal[‘fluorescence’, ‘temperature’]) – Whether to include dotted vertical lines on transitions between stages. If “fluorescence” or “temperature”, include only on one of the two axes.
annotate_stage_lines (bool | float | Literal[‘fluorescence’, ‘temperature’] | Tuple[Literal[‘fluorescence’, ‘temperature’], float]) – Whether to include text annotations for stage lines. Float parameter allows setting the minimum duration of stage, as a fraction of total plotted time, to annotate, in order to avoid overlapping annotations (default threshold is 0.05).
annotate_events (bool) – Whether to include annotations for events (drawer open/close, cover open/close).
figure_kw (dict[str, Any] | None) – Optional. A dictionary of options passed through as keyword options to the figure creation. Only applies if ax is None.
line_kw (dict[str, Any] | None) – Optional. A dictionary of keywords passed to fluorescence plot commands.
- Return type:
Sequence[Axes]
- plot_over_time_altair(samples=None, filters=None, stages=None, process=(), start_time='experiment', duration_units='hours', show_legend=True)[source]¶
- plot_protocol(ax=None)[source]¶
A plot of the temperature and data collection points in the experiment’s protocol.
- plot_temperatures(*, sel=None, times=None, ax=None, stage_lines=True, annotate_stage_lines=True, annotate_events=True, legend=False, figure_kw=None, line_kw=None, time_units='h', method='matplotlib')[source]¶
Plot sample temperature readings.
- Parameters:
sel (
Optional[Expr]) – A selector for the temperature DataFrame. This is not necessarily easy to use; times is an easier alternative.times (
Optional[tuple[float,float]]) – Constructs a selector to show temperatures for a time range (after activestarttime). :param:`sel` should not be set. Time is in the units of :param:`time_units`.time_units (
Literal['h','m','s']) – The units of the time range, and units to plot. “h” for hours, “m” for minutes, “s” for seconds.ax (
Optional[Axes]) – Optional. An axes to put the plot on. If not provided, the function will create a new figure, by default with constrained_layout=True, though this can be modified with figure_kw.stage_lines (
bool) – Whether to include dotted vertical lines on transitions between stages.annotate_stage_lines (
bool|float) – Whether to include text annotations for stage lines. Float parameter allows setting the minimum duration of stage, as a fraction of total plotted time, to annotate, in order to avoid overlapping annotations (default threshold is 0.05).annotate_events (
bool) – Whether to include annotations for events (cover opening/closing, drawer opening/closing).legend (
bool) – Whether to add a legend.figure_kw (
Optional[Mapping[str,Any]]) – Optional. A dictionary of options passed through as keyword options to the figure creation. Only applies if ax is None.line_kw (
Optional[Mapping[str,Any]]) – Optional. A dictionary of keywords passed to plot commands.method (
Literal['matplotlib','altair'])
- Return type:
- property quant_data_from_tiffs_polars: DataFrame¶
Quant data computed from TIFF images + ROI calibration.
Produces the same DataFrame as quant_data_polars but always uses TIFF images rather than pre-computed .quant files.
- property quant_data_polars: DataFrame¶
Raw quant data as a Polars DataFrame.
Uses pre-computed .quant files if available, otherwise falls back to computing from TIFF images + ROI calibration.
- property raw_data: DataFrame¶
- resume(machine=None)[source]¶
If this experiment is running, resume it.
Requires and takes exclusive Controller access on the machine.
- Raises:
NotRunningError – the experiment is not currently running
- Return type:
- property roi_calibration¶
ROI calibration data parsed from roi.ini.
- run(machine=None, overwrite=False, require_exclusive=False, require_drawer_check=True)[source]¶
Load the run onto a machine, and start it.
- Parameters:
machine (
Union[str,Machine,None]) – The machine to run on, by default None, in which case the machine associated with the run (if any) is used.overwrite (bool or "incomplete", optional) – Whether to overwrite files if a run with the same name already exists. If “incomplete”, only overwrite if the existing run is an incomplete folder (in the experiments: working directory). By default False.
require_exclusive (bool, optional) – Whether to require exclusive access to the machine, by default False.
require_drawer_check (bool, optional) – Whether to ensure the drawer is closed before starting. Note that a close command will be sent regardless of this setting. By default True.
- Raises:
MachineBusyError – The machine isn’t idle.
AlreadyExistsError (either AlreadyExistsWorkingError or AlreadyExistsCompleteError) – The machine already has a folder or eds file with this run name.
- Return type:
-
runendtime:
datetime|None¶ The run end time as a datetime, taken from the log. This is the end of the run,
-
runstarttime:
datetime|None¶ The run start time as a datetime. This is taken directly from the log, ignoring the software-set value and replacing it on save if possibe. It is defined as the moment the machine records “Run Starting” in its log, using its timestamp. This may be 3 minutes before the start of the protocol if the lamp needs to warm up. It should be the same value as defined by AB’s software.
Use
activestarttimefor a more accurate value.None if the file has not been updated since the start of the run
-
runstate:
Literal['INIT','RUNNING','COMPLETE','ABORTED','STOPPED','UNKNOWN']¶ Run state, possible values INIT, RUNNING, COMPLETE, ABORTED, STOPPED(?).
- property runtitle_safe: str¶
Run name with “ “ replaced by “_”; raises ValueError if name has other problematic characters.
- property sample_wells: _SampleWellsView¶
A dictionary of sample names to sample wells (convenience read/write access to the
PlateSetup.
- save_file(path_or_stream='.', overwrite=False, update_files=True)[source]¶
Save an EDS file of the experiment. This should be readable by AB’s software, but makes no attempt to hide that it was written by QSLib, and contains some other information. By default, this will refuse to overwrite an existing file.
- Parameters:
path_or_stream (str or os.PathLike[str] or io.BytesIO) – A filename, open binary IO, or directory. If a directory, the file will be saved with the name from Experiment.runtitle_safe.
overwrite (bool, optional) – If True, overwrite any existing file without warning. Defaults to False.
update_files (bool, optional) – If True (default), update files before saving. Use False if you don’t want qslib to touch the files, for example, if you have just loaded a run from the machine and don’t want qslib to change anything based on its interpretation.
- Return type:
- stop(machine=None)[source]¶
If this experiment is running, stop it after the end of the current cycle.
Requires and takes exclusive Controller access on the machine.
- Raises:
NotRunningError – the experiment is not currently running
- Return type:
- sync_from_machine(machine=None, log_method='eval', include_tiffs=False)[source]¶
Try to synchronize the data in the experiment to the current state of the run on a machine, more efficiently than reloading everything.
- Return type:
- property temperature_ramps_polars: DataFrame¶
- property temperature_setpoints_polars: DataFrame¶
- property temperatures: DataFrame¶
A DataFrame of temperature readings, at one second resolution, during the experiment (and potentially slightly before and after, if included in the message log).
Columns (as multi-index):
- (“time”, …)float
Time of temperature reading, for choices of “timestamp” (Unix timestamp in seconds), “seconds” (seconds since the active start of the run), or “hours”. The latter two may be negative, and may not be set if the run never became active.
- (“sample”, …)float
Sample temperature for blocks 1, 2, …, 6, and average in “avg”.
- (“block”, …)float
Block temperature for blocks 1, 2, …, 6, and average in “avg”.
- (“other”, “cover”)float
Cover temperature
- (“other”, “heatsink”)float
Heatsink temperature
- property temperatures_polars: DataFrame¶
Long-format temperature log (one row per (timestamp, zone, kind)) with columns
timestamp(float seconds since epoch),temperature,zone(1-indexed, null for heatsink/cover),kind(one of “sample”, “block”, “heatsink”, “cover”), andtime(Datetime[ms, UTC]).For the 0.14-era wide schema with one column per zone, use
temperatures_polars_wide.
- property temperatures_polars_wide: DataFrame¶
a single row per timestamp with one column per (kind, zone) —
sample_1..N,heatsink,cover,block_1..N— andtimestampasDatetime[ms, UTC].The default
temperatures_polarsis long-format (one row per zone × kind); use this accessor if you need the legacy wide shape.- Type:
Wide-format temperature log matching the 0.14 schema
- property tiff_images: dict¶
Raw TIFF images as numpy arrays, keyed by (stage, cycle, step, point, filter_set, exposure_index).
Returns a dict mapping tuple keys to numpy uint16 arrays of shape (height, width).
- property welldata: DataFrame¶
A DataFrame with fluorescence reading information.
Deprecated since version 0.14.0: Use
filter_datainstead.Indices (multi-index) are (filter_set, stage, cycle, step, point), where filter_set is a string in familiar form (eg, “x1-m4”) and the rest are int.
Columns (as multi-index):
- (“time”, …)float
Time of the data collection, taken from the .quant file. May differ for different filter sets. Options are “timestamp” (unix timestamp in seconds), “seconds”, and “hours” (the latter two from the active start of the run).
- (well, option)float
Data for a well, with well formatted like “A05”. Options are “rt” (read temperature from .quant file), “st” (more stable temperature), and “fl” (fluorescence).
- (“exposure”, “exposure”)float
Exposure time from filterdata.xml. Misleading, because it only refers to the longest exposure of multiple exposures.
- class qslib.Machine(host, password=None, automatic=True, max_access_level=AccessLevel.Controller, port=None, ssl=None, client_certificate_path=None, client_key_path=None, server_ca_file=None, tls_server_name=None, _initial_access_level=AccessLevel.Observer)[source]¶
Bases:
objectA connection to a QuantStudio machine. The connection can be opened and closed, and reused. A maximum access level can be set and changed, which will prevent the access level from going above that level.
By default, the class tries to handle connections and access automatically.
- Parameters:
host (
str) – The host name or IP to connect to.password (
Optional[str]) – The password to use. Note that this class does not obscure or protect the password at all, because it should not be relied on for security. See Security Considerations for more information.automatic (
bool) – Whether or not to automatically handle connection, disconnection, and where possible, access level. Default True.max_access_level ("Observer", "Controller", "Administrator", or "Full") – The maximum access level to allow. This is not the initial access level, which will be Observer. The parameter can be changed later by changing the
max_access_levelattribute.port (
Optional[int]) – The port to connect to. If None, and ssl is None, then 7443 will be tried with SSL, and if it fails, then 7000 will be tried without SSL.ssl (
Optional[bool]) – Whether or not to use SSL. If None, then SSL will be chosen based on the port number.client_certificate_path (
Optional[str]) – Path to a PEM file containing the client certificate for TLS client authentication. The file may also contain the private key, or it can be provided separately via client_key_path.client_key_path (
Optional[str]) – Path to a PEM file containing the client private key for TLS client authentication. Only needed if the key is not included in client_certificate_path.server_ca_file (
Optional[str]) – Path to a PEM file containing CA certificate(s) for verifying the server’s certificate. If not provided, server certificate verification is disabled (default).tls_server_name (
Optional[str]) – Expected server name for TLS hostname verification. If server_ca_file is provided but tls_server_name is None, certificate chain verification is performed but hostname is not checked. This is useful when connecting through tunnels or port forwards where the connection hostname differs from the certificate’s CN/SAN.
- property access_level: AccessLevel¶
- property block: tuple[bool, float]¶
Returns whether the block is currently temperature-controlled, and the current block temperature setting.
- compile_eds(run_name)[source]¶
Take a finished run directory in experiments:, compile it into an EDS, and move it to public_run_complete:
- Return type:
- property connected: bool¶
Whether or not there is a current connection to the machine.
Note that when using automatic connections, this will usually be False, because connections will only be active when running a command.
- property connection: QSConnection¶
The
QSConnectionfor the connection, or aConnectionError.
- cover_lower(check=True, ensure_drawer=True)[source]¶
Lower/engage the plate cover, closing the drawer if needed.
- Return type:
- property cover_position: Literal['Up', 'Down', 'Unknown', '']¶
Return the cover position from the ENG? command. Note that this does not always seem to work.
- define_protocol(protocol)[source]¶
Send a protocol to the machine. This is not related to a particular experiment. The name on the machine is set by the protocol.
- drawer_close(lower_cover=True, check=True)[source]¶
Close the machine drawer using the OPEN command. This will ensure proper cover/drawer operation. It will not check run status, and will open and close the drawer during runs and potentially during imaging.
By default, it will lower the cover automaticaly after closing, use lower_cover=False to not do so.
- Return type:
- drawer_open()[source]¶
Open the machine drawer using the OPEN command. This will ensure proper cover/drawer operation. It will not check run status, and will open and close the drawer during runs and potentially during imaging.
- Return type:
- property drawer_position: Literal['Open', 'Closed', 'Unknown']¶
Return the drawer position from the DRAW? command.
- generate_random_key()[source]¶
Generate a 6-digit random authentication key on the server.
Requires Controller or higher access. The key is valid for 10 minutes and grants Administrator access when used with
authenticate. Only one key is active at a time; calling this again before the key expires returns the same key.- Return type:
- Returns:
A 6-digit string (e.g., “042371”).
- get_all_filterdata(run=None, as_list=False)[source]¶
Fetch all filterdata from the machine.
Returns a list of Rust PlateData objects (as_list=True) or a Polars DataFrame.
- Return type:
- get_filterdata_one(ref, *, run=None, return_files=False)[source]¶
Fetch a single filterdata reading from the machine.
Returns a Rust PlateData object with timestamp set from quant data.
- Return type:
- get_zone_count()[source]¶
Query the number of temperature control zones from the server.
- Return type:
- Returns:
The number of zones (typically 6 for current QuantStudio instruments).
- list_files(path, *, leaf='FILE', verbose=False, recursive=False)[source]¶
- Return type:
list[str] |list[FileListInfo]
- property max_access_level: AccessLevel¶
- property power: bool¶
Get and set the machine’s operational power (lamp, etc) as a bool.
Setting this to False will not turn off the machine, just power down the lamp, temperature control, etc. It will do so even if there is currently a run.
- read_dir_as_zip(path, leaf='FILE')[source]¶
Read a directory on the
- Parameters:
- Returns:
the returned zip file
- Return type:
- restart_system()[source]¶
Restart the system (both the InstrumentServer and android interface) by killing the zygote process.
- Return type:
- run_command(command)[source]¶
Run a SCPI command, and return the response as a string. Waits for OK, not just NEXT.
- Parameters:
command (str) – command to run
- Returns:
Response message (after “OK”, not including it)
- Return type:
- Raises:
CommandError – Received an Error response.
- run_command_bytes(command)[source]¶
Run an SCPI command, and return the response as bytes (undecoded). Returns after the command is processed (OK or NEXT), but potentially before it has completed (NEXT).
- Parameters:
command (
str|bytes|SCPICommand) – command to run- Returns:
Response message (after “OK” or “NEXT”, likely “” in latter case)
- Return type:
- Raises:
CommandError – Received
- run_command_to_ack(command)[source]¶
Run an SCPI command, and return the response as a string. Returns after the command is processed (OK or NEXT), but potentially before it has completed (NEXT).
- Parameters:
commands – command to run
- Returns:
Response message (after “OK” or “NEXT”, likely “” in latter case)
- Return type:
- Raises:
CommandError – Received an Error response.
- run_command_to_bytes(command)[source]¶
Run an SCPI command, and return the response as bytes (undecoded). Waits for NEXT.
- Return type:
- save_run_from_storage(machine_path, download_path, overwrite=False)[source]¶
Download a file from run storage on the machine.
- set_status_led(color, mode='on')[source]¶
Set the front-panel status LED.
This is the machine’s indicator light, not the optical excitation lamp.
- Parameters:
color (
StatusLedColor|str) – One of red, green, blue, yellow, cyan, magenta, white (aStatusLedColoror its name, case-insensitive).mode (
StatusLedMode|str) – “on” (solid, the default), “blink”, or “off” (aStatusLedModeor its name).
- Return type:
Notes
Requires Controller access.
- property status_led: StatusLedState¶
Current color and mode of the front-panel status LED.
Reading returns a
StatusLedState(.colorisNonewhen off). Setting accepts a color name/StatusLedColor(solid on), or a(color, mode)tuple.
- class qslib.MachineStatus¶
Bases:
objectStatus of the machine hardware (temperatures, drawer, cover, etc.).
- block_temperatures¶
- static command()¶
- cover¶
- cover_temperature¶
- drawer¶
- static from_bytes(response)¶
- lamp_status¶
- led_temperature¶
- sample_temperatures¶
- target_controlled¶
- target_temperatures¶
- class qslib.NormRaw[source]¶
Bases:
ProcessorA Processor that takes no arguments and passes through raw fluorescence values.
- class qslib.NormToMaxPerWell(stage=None, step=None, cycle=None, point=None, *, expr=None, selection=None)[source]¶
Bases:
ProcessorA Processor that divides the fluorescence reading for each (filterset, well) pair by the max value of that pair within a particular selection of data.
See NormToMeanPerWell for usage examples.
- class qslib.NormToMeanPerWell(stage=None, step=None, cycle=None, point=None, *, expr=None, selection=None)[source]¶
Bases:
ProcessorA Processor that divides the fluorescence reading for each (filterset, well) pair by the mean value of that pair within a particular selection of data.
The easiest way to use this is to give a particular stage (all data in that stage will be used), or a stage and set of cycles (those cycles in that stage will be used). For example:
To normalize to the mean stage 8 values, use NormToMeanPerWell(stage=8).
- To normalize to the first 5 cycles of stage 2, use
NormToMeanPerWell(stage=2, cycle=range(1, 6)).
For Polars, use expr for custom filter expressions. For Pandas, use selection for arbitrary indexing.
- class qslib.PlateSetup(sample_wells=None, samples=(), plate_type=96)[source]¶
Bases:
object- classmethod from_array(array)[source]¶
Given an (8,12) or (16,24) array of sample names, create a PlateSetup. Interprets None, “None”, and “null” as empty wells.
- Return type:
- classmethod from_picklist(picklist, plate_name=None, labware=None)[source]¶
Create a PlateSetup from a Kithairon PickList.
- Parameters:
picklist (PickList or str) – The picklist to read. If a string, it is treated as a path to a CSV picklist.
plate_name (str or None) – The destination plate that the PlateSetup is for. If None, and there is only one destination plate, that one is used. If there are multiple destination plates, the user must specify one.
labware (Labware or None) – The Kithairon labware to use. If None, the default labware is used.
- Raises:
ValueError – If: - There is more than one destination plate and no plate_name is specified. - There are multiple sample names in a single well. - The destination plate is not a destination plate type in the Labware. - The destination plate shape is not 96 or 384 (taken from Labware)
- Return type:
Self
- classmethod from_xml_string(xml)[source]¶
Create a PlateSetup from an XML string (or bytes).
Uses Rust XML parsing internally.
- Return type:
- get_wells(samples_or_wells)[source]¶
Given a sample, well, or list of the two, returns the corresponding wells. Note that this relies on samples not having well-like names.
- property sample_wells¶
- to_xml_string(existing_xml=None)[source]¶
Serialize this PlateSetup to an XML string.
If existing_xml is provided, the existing XML structure is preserved and only the sample data is updated. Otherwise a new XML structure is created.
Uses Rust XML handling internally.
- Return type:
- property well_samples: Series¶
- class qslib.Processor[source]¶
Bases:
objectBase class for fluorescence data processors.
Processors transform fluorescence data (normalization, smoothing, etc.) and work with both Polars and Pandas DataFrames automatically. The process() method detects the input type and applies the appropriate implementation.
For Pandas, there’s also process_scoped() for scope-aware processing.
- process(data)[source]¶
Process the data, auto-detecting whether it’s Polars or Pandas.
- Parameters:
data (pl.LazyFrame, pl.DataFrame, or pd.DataFrame) – The fluorescence data to process.
- Returns:
The processed data.
- Return type:
Same type as input
- process_scoped(data, scope)[source]¶
Process Pandas data only if scope matches this processor’s scope.
This is useful for writing scope-agnostic code, provided that you call this for every scope before using the data.
- Parameters:
data (pd.DataFrame) – The fluorescence data to process.
scope ("all" or "limited") –
“all”: the entire welldata array.
”limited”: all time points, but limited to the filter sets and samples being plotted.
- Returns:
The processed data (or unchanged if scope doesn’t match).
- Return type:
pd.DataFrame
- class qslib.Protocol(stages=NOTHING, name=NOTHING, volume=50.0, runmode='standard', filters=NOTHING, covertemperature=105.0, prerun=NOTHING, postrun=NOTHING, classname='Protocol')[source]¶
Bases:
ProtoCommandA run protocol for the QuantStudio. Protocols encapsulate the temperature and camera controls for an entire run. They are composed of
Stage`s, which may repeat for a number of cycles, and the stages are in turn composed of Steps, which may be created for usual cases with :class:`Step, or from SCPI commands. Steps may repeat their contents as well, but this is not yet implemeted.- Parameters:
stages (Iterable[Stage]) – The stages of the protocol, likely
Stage.stage (_NumOrRefIndexer[Stage]) – A more convenient way of accessing the stages of the protocol, with numbering that matches the machine.
name (str | None) – A protocol name. If not set, a timestamp will be used, unlike AB’s uuid.
volume (float) – The sample volume, in µL.
runmode (str | None) – The run mode.
covertemperature (float (default 105.0)) – The cover temperature
filters (Sequence[str]) – A list of default filters that can be used by any collection commands that don’t specify their own.
prerun (Sequence[SCPICommand]) – Sets PRERUN. DO NOT USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.
postrun (Sequence[SCPICommand]) – Sets POSTRUN. DO NOT USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.
Notes
Protocol equality is based on functional attributes (stages, volume, runmode, filters, covertemperature, prerun, postrun) but excludes the name. This means two protocols with identical configurations but different names are considered equal.
- property all_filters: Collection[FilterSet]¶
A list of all filters used at some point in the protocol.
- property all_points: DataFrame¶
- check_compatible(new, status)[source]¶
Checks compatibility for changing a running protocol to a new one.
Raises ValueError if incompatible, returns True if compatible.
- Parameters:
- Raises:
ValueError – Protocols are incompatible.
- Return type:
- property dataframe: DataFrame¶
A DataFrame of the temperature protocol.
- classmethod from_scpi_string(text)[source]¶
Parse a Protocol from an SCPI command string.
- Return type:
-
postrun:
Sequence[SCPICommandLike]¶
-
prerun:
Sequence[SCPICommandLike]¶
- property stage: _NumOrRefIndexer[Stage]¶
A more convenient view of
Protocol.stages. This allows one-indexed access, such that protocol.stage[5] == protocol.stages[6] is stage 5 of the protocol, in the interpretation of tha machine. Indexing can use slices, and is inclusive, so protocol.stage[5:6] returns stages 5 and 6. Getting, setting, and appending stages are all supported through this interface.
- to_scpi_string_rust()[source]¶
Serialize this protocol to an SCPI string using the Rust implementation.
- Return type:
- class qslib.RunStatus¶
Bases:
objectStatus of the current run on the machine.
- static command()¶
- cycle¶
- static from_bytes(response)¶
- name¶
- num_cycles¶
- num_stages¶
- point¶
- stage¶
PRERUN = 0, numbered stage k = k, POSTRUN = N + 1.
- Type:
Stage position
- stage_name¶
Raw stage token reported by the machine.
- state¶
- step¶
- class qslib.Sample(name, uuid=None, color=None, properties=None, description=None, wells=None)¶
Bases:
object- color¶
Get color as RGBA tuple (matching Python Sample API)
- color_hex¶
Get color as hex string (#rrggbbaa)
- color_rgba¶
Get color as RGBA tuple (alias for color getter)
- description¶
- get_properties()¶
Get all properties as a dictionary
- get_property(key)¶
Get a property value by key
- name¶
- py_set_name¶
- set_color_hex(color)¶
Set color from hex string
- set_property(key, value)¶
Set a property
- to_record()¶
- uuid¶
- wells¶
- class qslib.SmoothEMWMean(com=None, span=None, halflife=None, alpha=None, min_periods=0, adjust=True, ignore_na=False)[source]¶
Bases:
ProcessorA Processor that smooths fluorescence readings using an exponentially weighted moving average (EWMA).
- class qslib.SmoothWindowMean(window, min_periods=None, center=False, win_type=None, closed=None)[source]¶
Bases:
ProcessorA Processor that smooths fluorescence readings using a rolling window mean.
- class qslib.Stage(steps, repeat=1, index=None, label=None, default_filters=())[source]¶
Bases:
ProtoCommandA Stage in a protocol, composed of
Steps with a possible repeat.- dataframe(start_time=0, previous_temperatures=None)[source]¶
Create a dataframe of the steps in this stage.
- Parameters:
start_time (
float) – The initial start time, in seconds, of the stage (before the ramp to the first step). Default is 0.previous_temperatures (
Optional[list[float]]) – A list of temperatures at the end of the previous stage, to allow calculation of ramp time. If None, the ramp is assumed to take no time.
- Return type:
DataFrame
- classmethod hold_at(temperature, total_time, step_time=None, collect=None, filters=())[source]¶
Hold at a temperature for a set amount of time, with steps of a configurable fixed time.
- Parameters:
temperatures – The temperature or temperatures to hold. If not strings or quantities, the value/values are interpreted as °C.
total_time (
int|str|Quantity) – Desired total time for the stage. If this is not a multiple of step_time, it may not be the actual total time for the stage. The function will emit a warning if the difference is more than 10%. If an integer, value is interpreted as seconds.step_time (
Union[int,str,Quantity,None]) – If None (default), the stage will have one step. Otherwise, it will have steps of this time. If an integer, value is interpreted as seconds.collect (
Optional[bool]) – Whether or not each step should collect fluorescence data. If None (default), collects data if filters is explicitly set.filters (
Sequence[str|FilterSet]) – A list of filters to collect. If empty, and collect is True, then each step will collect the default filters for theProtocol.
- Returns:
The resulting Stage
- Return type:
- Raises:
ValueError – If step time is larger than total time.
- classmethod hold_for(temperature, total_time, step_time=None, collect=None, filters=())¶
Hold at a temperature for a set amount of time, with steps of a configurable fixed time.
- Parameters:
temperatures – The temperature or temperatures to hold. If not strings or quantities, the value/values are interpreted as °C.
total_time (
int|str|Quantity) – Desired total time for the stage. If this is not a multiple of step_time, it may not be the actual total time for the stage. The function will emit a warning if the difference is more than 10%. If an integer, value is interpreted as seconds.step_time (
Union[int,str,Quantity,None]) – If None (default), the stage will have one step. Otherwise, it will have steps of this time. If an integer, value is interpreted as seconds.collect (
Optional[bool]) – Whether or not each step should collect fluorescence data. If None (default), collects data if filters is explicitly set.filters (
Sequence[str|FilterSet]) – A list of filters to collect. If empty, and collect is True, then each step will collect the default filters for theProtocol.
- Returns:
The resulting Stage
- Return type:
- Raises:
ValueError – If step time is larger than total time.
- property step: _NumOrRefIndexer[CustomStep]¶
- classmethod stepped_ramp(from_temperature, to_temperature, total_time, *, n_steps=None, temperature_step=None, points_per_step=1, collect=None, filters=(), start_increment=False)[source]¶
Hold at a series of temperatures, from one to another.
- Parameters:
from_temperature (
Union[float,str,Quantity,Sequence[float]]) – Initial temperature/s (inclusive). If None, uses the final temperature of the previous stage (FIXME: None is not currently handled).to_temperature (
Union[float,str,Quantity,Sequence[float]]) – Final temperature/s (inclusive).total_time (
int|str|Quantity) – Total time for the stagen_steps (
Optional[int]) – Number of steps. If None, uses 1.0 Δ°C steps, or, if doing a multi-temperature change, uses maximum step of 1.0 Δ°C. If n_steps is specified, it is the number of temperature steps to take. Normally, since there is an initial cycle of the starting temperatures, this means there will be n_steps + 1 cycles. If start_increment is True, and the initial cycle is already stepped away from the starting temperature, then there will be only n_steps cycles.temperature_step (
Union[float,str,Quantity,None]) – Step temperature change (optional). Must be None, or correctly match calculation, if n_steps is not None. If both this and n_steps are None, default is 1.0 Δ°C steps. If temperature step does not exactly fit range, it will be adjusted, with a warning if the change is more than 5%. Sign is ignored. If doing a multi-temperature change, then this is the maximum temperature step.collect (
Optional[bool]) – Collect data? If None, collects data if filters is set explicitly.start_increment (
bool) – If False (default), start at the from_temperature, holding there for the same hold time as every other temperature. If True, start one step away from the from_temperature. This is useful, for example, if the previous stage held at a particular temperature, and you now want to step away from that temperature. When True, note the remarks about n_steps above.
- Returns:
The resulting stage.
- Return type:
-
steps:
Sequence[CustomStep]¶
- class qslib.StatusLedColor(value)¶
Bases:
objectColor of the front-panel status LED.
The status LED is the machine’s indicator light, distinct from the optical excitation lamp. The seven colors and their numeric codes match the firmware (statusled.mod): RED=1, GREEN=2, BLUE=3, YELLOW=4, CYAN=5, MAGENTA=6, WHITE=7.
- Blue = StatusLedColor.BLUE¶
- Cyan = StatusLedColor.CYAN¶
- Green = StatusLedColor.GREEN¶
- Magenta = StatusLedColor.MAGENTA¶
- Red = StatusLedColor.RED¶
- White = StatusLedColor.WHITE¶
- Yellow = StatusLedColor.YELLOW¶
- number¶
- value¶
- class qslib.StatusLedMode(value)¶
Bases:
objectMode of the status LED: solid on, off, or blinking.
- Blink = StatusLedMode.BLINK¶
- Off = StatusLedMode.OFF¶
- On = StatusLedMode.ON¶
- value¶
- class qslib.StatusLedSet(color, mode)¶
Bases:
objectSet the status LED to a color and mode.
Uses the low-level per-color verbs (LED:GREENON, LED:GREENBLINK, LED:GREENOFF), which are unrestricted — unlike the LED:<COLOR>:ON form, they set/clear any color including red.
- color¶
- command_string()¶
The SCPI command string, e.g. “LED:GREENON”.
- mode¶
- class qslib.StatusLedState¶
Bases:
objectCurrent color and mode of the status LED (from LED:STATus?).
color is None when the LED is off (the firmware reports the color as -).
- color¶
- static command()¶
- static from_bytes(response)¶
- mode¶
- class qslib.Step(time, temperature, collect=None, temp_increment=<Quantity(0.0, 'delta_degree_Celsius')>, temp_incrementcycle=2, temp_incrementpoint=None, time_increment=<Quantity(0, 'second')>, time_incrementcycle=2, time_incrementpoint=None, filters=(), pcr=False, quant=True, tiff=False, repeat=1, default_filters=())[source]¶
Bases:
CustomStepA normal protocol step, of a hold and possible collection.
- Parameters:
time (int) – The step time setting, in seconds.
temperature (float | Sequence[float]) – The temperature hold setting, either as a float (all zones the same) or a sequence (of correct length) of floats setting the temperature for each zone.
collect (
Optional[bool]) – Collect fluorescence data? If None (default), collect only if the Step has an explicit filters setting.temp_increment (float) – Amount to increment all zone temperatures per cycle on and after
temp_incrementcycle.temp_incrementcycle (int (default 2)) – First cycle to start the increment changes. Note that the default in QSLib is 2, not 1 (as in AB’s software), so that leaving this alone makes sense (the first cycle will be at
temperature, the next attemperature + temp_incrementcycle.time_increment (float)
time_incrementcycle (int) – The same settings for time per cycle.
filters (Sequence[FilterSet | str] (default empty)) – A list of filter pairs to collect, either using
FilterSetor a string like “x1-m4”. If collect is True and this is empty, then the filters will be set by the Protocol.
Notes
This currently does not support step-level repeats, which do exist on the machine.
- property body: list[ProtoCommand]¶
- duration_at_cycle_point(cycle, point=1)[source]¶
Durations of the step at cycle (from 1)
- Return type:
Quantity
- durations_at_cycle(cycle)[source]¶
Duration of the step (excluding ramp) at cycle (from 1)
- Return type:
list[Quantity]
-
temp_increment:
Quantity¶
-
temperature:
Quantity¶
- property temperature_list: Quantity¶
- temperatures_at_cycle(cycle)[source]¶
Temperatures of the step at cycle (from 1)
- Return type:
list[Quantity]
- temperatures_at_cycle_point(cycle, point)[source]¶
Temperatures of the step at cycle (from 1)
- Return type:
Quantity
-
time:
Quantity¶
-
time_increment:
Quantity¶
- class qslib.SubtractByMeanPerWell(stage=None, step=None, cycle=None, point=None, *, expr=None, selection=None)[source]¶
Bases:
ProcessorA Processor that subtracts the fluorescence reading for each (filterset, well) pair by the mean value of that pair within a particular selection of data.
See NormToMeanPerWell for usage examples.
- qslib.pandas_process(data, processors, scope='limited', ylabel=None)[source]¶
Apply processors to Pandas data.
- Parameters:
- Returns:
Processed data, optionally with updated ylabel.
- Return type:
pd.DataFrame or (pd.DataFrame, str)