riverine

Contents

riverine#

Submodules#

Attributes#

MultiFixedConcentration

MultiFixedVolume

DNAN

nM

uL

uM

ureg

html_with_borders_tablefmt

Pass this as the parameter tablefmt in any method that accepts that parameter to have the table

Exceptions#

VolumeError

Inappropriate argument value (of correct type).

Classes#

AbstractAction

Abstract class defining an action in a mix recipe.

EqualConcentration

An action adding an equal concentration of each component, without setting that concentration.

FixedConcentration

An action adding one or multiple components, with a set destination concentration per component (adjusting volumes).

FixedVolume

An action adding one or multiple components, with a set transfer volume.

ToConcentration

Add an amount of (non-mix) components to result in a fixed total concentration of each in the mix.

FillToVolume

Abstract class defining an action in a mix recipe.

AbstractComponent

Abstract class for a component in a mix. Custom components that don't inherit from

Component

A single named component, potentially with a concentration and location.

Strand

A single named strand, potentially with a concentration, location and sequence.

Experiment

A class collecting many related mixes and components, allowing methods to be run that consider all of them

WellPos

A Well reference, allowing movement in various directions and bounds checking.

Mix

Class denoting a Mix, a collection of source components mixed to

MixLine

Class for handling a line of a (processed) mix recipe.

Reference

Functions#

master_mix(, exclude_shared_components, list[Mix]])

Create a "master mix" useful for saving pipetting steps when creating Mix's in mixes

split_mix() → Mix)

A "split mix" is a Mix that involves creating a large volume mix and splitting it into several

hydrate_and_measure_conc_and_dilute(...)

Assuming hydrate() is called with parameters nmol and target_conc_high to give initial

measure_conc_and_dilute(...)

Calculates concentration of DNA sample given an absorbance reading on a NanoDrop machine,

load_reference(→ Reference)

Q_(→ DecimalQuantity)

Convenient constructor for units, eg, Q_(5.0, 'nM'). Ensures that the quantity is a Decimal.

Package Contents#

class riverine.AbstractAction[source]#

Abstract class defining an action in a mix recipe.

property name: str#
Abstractmethod:

abstractmethod mix_volume_effect(_cache_key=None)[source]#

The effect of the action on the mix volume.

Returns:

  • MixVolumeDep – How the mix volume affects the action.

  • DecimalQuantity – If MixVolumeDep is DETERMINES, the total mix volume that the action causes. If MixVolumeDep is DEPENDS, NAN. If MixVolumeDep is INDEPENDENT, the total volume that the action adds.

_get_name(_cache_key=None) str[source]#
tx_volume(mix_vol: riverine.units.DecimalQuantity = NAN_VOL, actions: riverine.units.Sequence[AbstractAction] = (), _cache_key=None) riverine.units.DecimalQuantity[source]#

The total volume transferred by the action to the sample. May depend on the total mix volume.

Parameters:

mix_vol – The mix volume. Does not accept strings.

abstractmethod _mixlines(tablefmt: str | riverine.printing.TableFormat, mix_vol: riverine.units.DecimalQuantity, actions: riverine.units.Sequence[AbstractAction] = (), _cache_key=None) riverine.units.Sequence[riverine.printing.MixLine][source]#
abstractmethod all_components(mix_vol: riverine.units.DecimalQuantity, actions: riverine.units.Sequence[AbstractAction] = (), _cache_key=None) pandas.DataFrame[source]#

A dataframe containing all base components added by the action.

Parameters:

mix_vol – The mix volume. Does not accept strings.

abstractmethod with_experiment(experiment: riverine.experiments.Experiment, *, inplace: bool = True) T[source]#

Returns a copy of the action updated from a experiment dataframe.

abstractmethod with_reference(reference: riverine.references.Reference, *, inplace: bool = False) T[source]#

Returns a copy of the action updated from a reference dataframe.

dest_concentration(mix_vol: riverine.units.DecimalQuantity, actions: riverine.units.Sequence[AbstractAction] = (), cache_key=None) riverine.units.DecimalQuantity[source]#

The destination concentration added to the mix by the action.

Raises:

ValueError – There is no good definition for a single destination concentration (the action may add multiple components).

dest_concentrations(mix_vol: riverine.units.DecimalQuantity, actions: riverine.units.Sequence[AbstractAction] = (), cache_key=None) riverine.units.Sequence[riverine.units.DecimalQuantity][source]#
property components: list[riverine.components.AbstractComponent]#
Abstractmethod:

property source_concentrations: list[riverine.units.DecimalQuantity]#
abstractmethod _get_source_concentrations(_cache_key=None) list[riverine.units.DecimalQuantity][source]#
abstractmethod each_volumes(mix_volume: riverine.units.DecimalQuantity, actions: riverine.units.Sequence[AbstractAction] = (), _cache_key=None) list[riverine.units.DecimalQuantity][source]#
classmethod _structure(d: dict[str, Any], experiment: riverine.experiments.Experiment) AbstractAction[source]#
Abstractmethod:

abstractmethod _unstructure(experiment: riverine.experiments.Experiment | None) dict[str, Any][source]#
class riverine.EqualConcentration(components: riverine.units.Sequence[riverine.components.AbstractComponent | str] | riverine.components.AbstractComponent | str, fixed_volume: str | riverine.units.DecimalQuantity, set_name: str | None = None, compact_display: bool = True, method: Literal['max_volume', 'min_volume', 'check'] | tuple[Literal['max_fill'], str] = 'min_volume', equal_conc: bool | str | None = None)[source]#

Bases: FixedVolume

An action adding an equal concentration of each component, without setting that concentration.

Depending on the setting of equal_conc, it may require that the concentrations all be equal to begin with, or may treat the fixed transfer volume as the volume as the minimum or maximum volume to transfer, adjusting volumes of each strand to make this work and have them at equal destination concentrations.

Parameters:
  • components – A list of Components.

  • fixed_volume – A fixed volume for the action. Input can be a string (eg, “5 µL”) or a pint Quantity. The interpretation of this depends on equal_conc.

  • set_name – The name of the mix. If not set, name is based on components.

  • compact_display – If True (default), the action tries to display compactly in mix recipes. If False, it displays each component as a separate line.

  • method – If “check”, the action still transfers the same volume of each component, but will raise a ValueError if this will not result in every component having the same concentration added (ie, if they have different source concentrations). If “min_volume”, the action will transfer at least fixed_volume of each component, but will transfer more for components with lower source concentration, so that the destination concentrations are all equal (but not fixed to a specific value). If “max_volume”, the action instead transfers at most fixed_volume of each component, tranferring less for higher source concentration components. If (‘max_fill’, buffer_name), the fixed volume is the maximum, while for every component that is added at a lower volume, a corresponding volume of buffer is added to bring the total volume of the two up to the fixed volume.

  • [ (>>> components =)

  • Component("c1" (...)

  • nM") ("200)

:param : :param … Component(“c2”: :param “200 nM”): :param : :param … Component(“c3”: :param “200 nM”): :param : :param … Component(“c4”: :param “100 nM”): :param … ]: :param >>> print(Mix([EqualConcentration(components: :param “5 uL”: :param method=”min_volume”)]: :param name=”example”)): :param Table: :type Table: Mix: example, Conc: 40.00 nM, Total Vol: 25.00 µl :param <BLANKLINE>: :param | Comp | Src [] | Dest [] | # | Ea Tx Vol | Tot Tx Vol | Loc | Note |: :param |: :type |: -----------|:———-|:----------|:—-|:------------|:————-|:------|:——-| :param | c1: :param c2: :param c3 | 200.00 nM | 40.00 nM | 3 | 5.00 µl | 15.00 µl | | |: :param | c4 | 100.00 nM | 40.00 nM | 1 | 10.00 µl | 10.00 µl | | |: :param >>> print(Mix([EqualConcentration(components: :param "5 uL": :param method="max_volume")]: :param name="example")): :param Table: :type Table: Mix: example, Conc: 40.00 nM, Total Vol: 12.50 µl :param <BLANKLINE>: :param | Comp | Src [] | Dest [] | # | Ea Tx Vol | Tot Tx Vol | Loc | Note |: :param |: :type |: -----------|:———-|:----------|:—-|:------------|:————-|:------|:——-| :param | c1: :param c2: :param c3 | 200.00 nM | 40.00 nM | 3 | 2.50 µl | 7.50 µl | | |: :param | c4 | 100.00 nM | 40.00 nM | 1 | 5.00 µl | 5.00 µl | | |:

__hash__#
method: Literal['max_volume', 'min_volume', 'check'] | tuple[Literal['max_fill'], str] = 'min_volume'#
property source_concentrations: list[riverine.units.DecimalQuantity]#
_get_source_concentrations(_cache_key=None) list[riverine.units.DecimalQuantity][source]#
each_volumes(mix_volume: riverine.units.DecimalQuantity = NAN_VOL, actions: riverine.units.Sequence[AbstractAction] = (), _cache_key=None) list[riverine.units.DecimalQuantity][source]#
tx_volume(mix_vol: riverine.units.DecimalQuantity = NAN_VOL, actions: riverine.units.Sequence[AbstractAction] = (), _cache_key=None) riverine.units.DecimalQuantity[source]#

The total volume transferred by the action to the sample. May depend on the total mix volume.

Parameters:

mix_vol – The mix volume. Does not accept strings.

_mixlines(tablefmt: str | riverine.printing.TableFormat, mix_vol: riverine.units.DecimalQuantity, actions: riverine.units.Sequence[AbstractAction] = (), _cache_key=None) list[riverine.printing.MixLine][source]#
mix_volume_effect(_cache_key=None)[source]#

The effect of the action on the mix volume.

Returns:

  • MixVolumeDep – How the mix volume affects the action.

  • DecimalQuantity – If MixVolumeDep is DETERMINES, the total mix volume that the action causes. If MixVolumeDep is DEPENDS, NAN. If MixVolumeDep is INDEPENDENT, the total volume that the action adds.

class riverine.FixedConcentration[source]#

Bases: ActionWithComponents

An action adding one or multiple components, with a set destination concentration per component (adjusting volumes).

FixedConcentration adds a selection of components, with a specified destination concentration.

Parameters:
  • components – A list of Components.

  • fixed_concentration – A fixed concentration for the action. Input can be a string (eg, “50 nM”) or a pint Quantity.

  • set_name – The name of the mix. If not set, name is based on components.

  • compact_display – If True (default), the action tries to display compactly in mix recipes. If False, it displays each component as a separate line.

  • min_volume – Specifies a minimum volume that must be transferred per component. Currently, this is for validation only: it will cause a VolumeError to be raised if a volume is too low.

Raises:

VolumeError – One of the volumes to transfer is less than the specified min_volume.

Examples

>>> from riverine.mixes import *
>>> components = [
...     Component("c1", "200 nM"),
...     Component("c2", "200 nM"),
...     Component("c3", "200 nM"),
...     Component("c4", "100 nM")
... ]
>>> print(Mix([FixedConcentration(components, "20 nM")], name="example", fixed_total_volume="25 uL"))
Table: Mix: example, Conc: 40.00 nM, Total Vol: 25.00 µl

| Comp       | Src []    | Dest []   | #   | Ea Tx Vol   | Tot Tx Vol   | Loc   | Note   |
|:-----------|:----------|:----------|:----|:------------|:-------------|:------|:-------|
| c1, c2, c3 | 200.00 nM | 20.00 nM  | 3   | 2.50 µl     | 7.50 µl      |       |        |
| c4         | 100.00 nM | 20.00 nM  |     | 5.00 µl     | 5.00 µl      |       |        |
| Buffer     |           |           |     |             | 12.50 µl     |       |        |
| *Total:*   |           | 40.00 nM  |     |             | 25.00 µl     |       |        |
fixed_concentration: riverine.units.DecimalQuantity#
set_name: str | None = None#
compact_display: bool = True#
min_volume: riverine.units.DecimalQuantity#
dest_concentrations(mix_vol: riverine.units.DecimalQuantity = NAN_VOL, actions: riverine.units.Sequence[AbstractAction] = (), _cache_key=None) list[riverine.units.DecimalQuantity][source]#
each_volumes(mix_volume: riverine.units.DecimalQuantity = NAN_VOL, actions: riverine.units.Sequence[AbstractAction] = (), _cache_key=None) list[riverine.units.DecimalQuantity][source]#
_mixlines(tablefmt: str | riverine.printing.TableFormat, mix_vol: riverine.units.DecimalQuantity, actions: riverine.units.Sequence[AbstractAction] = (), _cache_key=None) list[riverine.printing.MixLine][source]#
property name: str#
mix_volume_effect(_cache_key=None)[source]#

The effect of the action on the mix volume.

Returns:

  • MixVolumeDep – How the mix volume affects the action.

  • DecimalQuantity – If MixVolumeDep is DETERMINES, the total mix volume that the action causes. If MixVolumeDep is DEPENDS, NAN. If MixVolumeDep is INDEPENDENT, the total volume that the action adds.

class riverine.FixedVolume[source]#

Bases: ActionWithComponents

An action adding one or multiple components, with a set transfer volume.

Parameters:
  • components – A list of Components.

  • fixed_volume – A fixed volume for the action. Input can be a string (eg, “5 µL”) or a pint Quantity. The interpretation of this depends on equal_conc.

  • set_name – The name of the mix. If not set, name is based on components.

  • compact_display – If True (default), the action tries to display compactly in mix recipes. If False, it displays each component as a separate line.

Examples

>>> from riverine.mixes import *
>>> components = [
...     Component("c1", "200 nM"),
...     Component("c2", "200 nM"),
...     Component("c3", "200 nM"),
... ]
>>> print(Mix([FixedVolume(components, "5 uL")], name="example"))
Table: Mix: example, Conc: 66.67 nM, Total Vol: 15.00 µl

| Comp       | Src []    | Dest []   |   # | Ea Tx Vol   | Tot Tx Vol   | Loc   | Note   |
|:-----------|:----------|:----------|----:|:------------|:-------------|:------|:-------|
| c1, c2, c3 | 200.00 nM | 66.67 nM  |   3 | 5.00 µl     | 15.00 µl     |       |        |
fixed_volume: riverine.units.DecimalQuantity#
set_name: str | None = None#
compact_display: bool = True#
dest_concentrations(mix_vol: riverine.units.DecimalQuantity = NAN_VOL, actions: riverine.units.Sequence[AbstractAction] = (), _cache_key=None) list[riverine.units.DecimalQuantity][source]#
each_volumes(mix_volume: riverine.units.DecimalQuantity = NAN_VOL, actions: riverine.units.Sequence[AbstractAction] = (), _cache_key=None) list[riverine.units.DecimalQuantity][source]#
property name: str#
_get_name(_cache_key=None) str[source]#
_mixlines(tablefmt: str | riverine.printing.TableFormat, mix_vol: riverine.units.DecimalQuantity, actions: riverine.units.Sequence[AbstractAction] = (), _cache_key=None) list[riverine.printing.MixLine][source]#
mix_volume_effect(_cache_key=None)[source]#

The effect of the action on the mix volume.

Returns:

  • MixVolumeDep – How the mix volume affects the action.

  • DecimalQuantity – If MixVolumeDep is DETERMINES, the total mix volume that the action causes. If MixVolumeDep is DEPENDS, NAN. If MixVolumeDep is INDEPENDENT, the total volume that the action adds.

riverine.MultiFixedConcentration[source]#
riverine.MultiFixedVolume[source]#
class riverine.ToConcentration[source]#

Bases: ActionWithComponents

Add an amount of (non-mix) components to result in a fixed total concentration of each in the mix.

An action adding an amount of components such that the concentration of each component in the mix will be at some target concentration. Unlike FixedConcentration, which adds a certain concentration, this takes into account other contents of the mix, and only adds enough to reach a particular final concentration.

fixed_concentration: riverine.units.DecimalQuantity#
compact_display: bool = True#
min_volume: riverine.units.DecimalQuantity#
_othercomps(mix_vol: riverine.units.DecimalQuantity, actions: riverine.units.Sequence[AbstractAction] = (), _cache_key=None)[source]#
dest_concentrations(mix_vol: riverine.units.DecimalQuantity, actions: riverine.units.Sequence[AbstractAction] = (), _cache_key=None) riverine.units.Sequence[riverine.units.DecimalQuantity][source]#
each_volumes(mix_volume: riverine.units.DecimalQuantity = NAN_VOL, actions: riverine.units.Sequence[AbstractAction] = (), _cache_key=None) list[riverine.units.DecimalQuantity][source]#
_mixlines(tablefmt: str | riverine.printing.TableFormat, mix_vol: riverine.units.DecimalQuantity, actions: riverine.units.Sequence[AbstractAction] = (), _cache_key=None) list[riverine.printing.MixLine][source]#
mix_volume_effect(_cache_key=None)[source]#

The effect of the action on the mix volume.

Returns:

  • MixVolumeDep – How the mix volume affects the action.

  • DecimalQuantity – If MixVolumeDep is DETERMINES, the total mix volume that the action causes. If MixVolumeDep is DEPENDS, NAN. If MixVolumeDep is INDEPENDENT, the total volume that the action adds.

class riverine.FillToVolume[source]#

Bases: ActionWithComponents

Abstract class defining an action in a mix recipe.

target_total_volume: riverine.units.DecimalQuantity#
dest_concentrations(mix_vol: riverine.units.DecimalQuantity = NAN_VOL, actions: riverine.units.Sequence[AbstractAction] = (), _cache_key=None) list[riverine.units.DecimalQuantity][source]#
each_volumes(mix_volume: riverine.units.DecimalQuantity = NAN_VOL, actions: riverine.units.Sequence[AbstractAction] = (), _cache_key=None) list[riverine.units.DecimalQuantity][source]#
_mixlines(tablefmt: str | riverine.printing.TableFormat, mix_vol: riverine.units.DecimalQuantity, actions: riverine.units.Sequence[AbstractAction] = (), _cache_key=None) list[riverine.printing.MixLine][source]#
mix_volume_effect(_cache_key=None)[source]#

The effect of the action on the mix volume.

Returns:

  • MixVolumeDep – How the mix volume affects the action.

  • DecimalQuantity – If MixVolumeDep is DETERMINES, the total mix volume that the action causes. If MixVolumeDep is DEPENDS, NAN. If MixVolumeDep is INDEPENDENT, the total volume that the action adds.

class riverine.AbstractComponent[source]#

Bases: abc.ABC

Abstract class for a component in a mix. Custom components that don’t inherit from a concrete class should inherit from this class and implement the methods here.

property name: str#
Abstractmethod:

Name of the component.

property location: tuple[str, riverine.locations.WellPos | None]#
property plate: str | None#
property is_mix: bool#
property well: riverine.locations.WellPos | None#
property _well_list: list[riverine.locations.WellPos]#
property volume: riverine.units.DecimalQuantity#
property concentration: riverine.units.DecimalQuantity#
Abstractmethod:

(Source) concentration of the component as a pint Quantity. NaN if undefined.

abstractmethod all_components() pandas.DataFrame[source]#

A dataframe of all components.

abstractmethod with_reference(reference: riverine.references.Reference, *, inplace: bool = False) T[source]#
abstractmethod with_experiment(experiment: riverine.experiments.Experiment, *, inplace: bool = True) AbstractComponent[source]#
classmethod _structure(d: dict[str, Any], experiment: riverine.experiments.Experiment | None = None) AbstractComponent[source]#
Abstractmethod:

abstractmethod _unstructure(experiment: riverine.experiments.Experiment | None = None) dict[str, Any][source]#
printed_name(tablefmt: str | riverine.printing.TableFormat) str[source]#
_update_volumes(consumed_volumes: dict[str, riverine.units.DecimalQuantity] | None = None, made_volumes: dict[str, riverine.units.DecimalQuantity] | None = None, _cache_key=None) Tuple[dict[str, riverine.units.DecimalQuantity], dict[str, riverine.units.DecimalQuantity]][source]#

Given a

class riverine.Component[source]#

Bases: AbstractComponent

A single named component, potentially with a concentration and location.

Location is stored as a plate and well property. plate is

name: str#

Name of the component.

_get_name(_cache_key=None) str[source]#
concentration: riverine.units.DecimalQuantity#

(Source) concentration of the component as a pint Quantity. NaN if undefined.

_get_concentration(_cache_key=None) riverine.units.DecimalQuantity[source]#
plate: str | None#
well: riverine.locations.WellPos | None#
volume: riverine.units.DecimalQuantity#
property location: tuple[str | None, riverine.locations.WellPos | None]#
all_components_polars(_cache_key=None) polars.DataFrame[source]#
all_components() pandas.DataFrame[source]#

A dataframe of all components.

_unstructure(experiment: riverine.experiments.Experiment | None = None) dict[str, Any][source]#
classmethod _structure(d: dict[str, Any], experiment: riverine.experiments.Experiment | None = None) Component[source]#
with_experiment(experiment: riverine.experiments.Experiment, inplace: bool = True) AbstractComponent[source]#
with_reference(reference: riverine.references.Reference, inplace: bool = False) Component[source]#
class riverine.Strand[source]#

Bases: Component

A single named strand, potentially with a concentration, location and sequence.

sequence: str | None = None#
with_reference(reference: riverine.references.Reference, inplace: bool = False) Strand[source]#
class riverine.Experiment[source]#

A class collecting many related mixes and components, allowing methods to be run that consider all of them together.

Components can be referenced, and set, by name with [], and can be iterated through.

__hash__#
components: dict[str, riverine.components.AbstractComponent]#
volume_checks: bool = True#
reference: riverine.references.Reference | None#
locations: LocationDict#
generate_picklist(_cache_key=None) Experiment.generate_picklist.PickList[source]#
add(component: riverine.components.AbstractComponent, *, check_volumes: bool | None = None, apply_reference: bool = True, check_existing: bool | Literal['equal'] = 'equal') Experiment[source]#
add_mix(mix_or_actions: riverine.mixes.Mix | Sequence[riverine.actions.AbstractAction] | riverine.actions.AbstractAction, name: str = '', test_tube_name: str | None = None, *, fixed_total_volume: riverine.units.DecimalQuantity | str | None = None, fixed_concentration: str | riverine.units.DecimalQuantity | None = None, buffer_name: str = 'Buffer', min_volume: riverine.units.DecimalQuantity | str = Q_('0.5', uL), check_volumes: bool | None = None, apply_reference: bool = True, check_existing: bool | Literal['equal'] = 'equal') Experiment[source]#

Add a mix to the experiment, either as a Mix object, or by creating a new Mix.

Either the first argument should be a Mix, or arguments should be passed as for initializing a Mix.

If check_volumes is True (by default), the mix will be added to the experiment, and volumes checked. If the mix causes a volume usage problem, it will not be added to the Experiment, and a VolumeError will be raised.

If check_existing is True (by default), then a exception is raised if the experiment already contains a mix with the name name. Otherwise, the existing mix is replaced with the new mix.

__setitem__(name: str, mix: riverine.components.AbstractComponent) None[source]#
get(key: str, default=None)[source]#
__getitem__(name: str) riverine.components.AbstractComponent[source]#
__delitem__(name: str) None[source]#
__contains__(name: str) bool[source]#
remove_mix(name: str) None[source]#

Remove a mix from the experiment, referenced by name,

remove(name: str) None[source]#

Remove a mix from the experiment, referenced by name,

__len__() int[source]#
__iter__() Iterator[riverine.components.AbstractComponent][source]#
consumed_and_produced_volumes() Mapping[str, Tuple[riverine.units.DecimalQuantity, riverine.units.DecimalQuantity]][source]#
check_volumes(showall: bool = False, display: bool = True, raise_error: bool = False) str | None[source]#

Check to ensure that consumed volumes are less than made volumes.

_unstructure() dict[str, Any][source]#

Create a dict representation of the Experiment.

classmethod _structure(d: dict[str, Any]) Experiment[source]#

Create an Experiment from a dict representation.

classmethod load(filename_or_stream: str | os.PathLike | TextIO) Experiment[source]#

Load an experiment from a JSON-formatted file created by Experiment.save.

resolve_components() None[source]#

Resolve string/blank-component components in mixes, searching through the mixes in the experiment. FIXME Add used mixes to the experiment if they are not already there.

save(filename_or_stream: str | os.PathLike | TextIO) None[source]#

Save an experiment to a JSON-formatted file.

Tries to store each component/mix only once, with other mixes referencing those components.

use_reference(reference: riverine.references.Reference) Experiment[source]#

Apply a Reference, in place, to all components in the Experiment.

class riverine.WellPos(ref_or_row: int, col: int, /, *, platesize: Literal[96, 384] = 384)[source]#
class riverine.WellPos(ref_or_row: str, col: None = None, /, *, platesize: Literal[96, 384] = 384)

A Well reference, allowing movement in various directions and bounds checking.

This uses 1-indexed row and col, in order to match usual practice. It can take either a standard well reference as a string, or two integers for the row and column.

row: int#
col: int#
platesize: Literal[96, 384] = 384#
_validate_row(v: int) None[source]#
_validate_col(v: int) None[source]#
__str__() str[source]#
__repr__() str[source]#
__eq__(other: object) bool[source]#
key_byrow() tuple[int, int][source]#

Get a tuple (row, col) key that can be used for ordering by row.

key_bycol() tuple[int, int][source]#

Get a tuple (col, row) key that can be used for ordering by column.

next_byrow() WellPos[source]#

Get the next well, moving right along rows, then down.

next_bycol() WellPos[source]#

Get the next well, moving down along columns, and then to the right.

is_last() bool[source]#
Returns:

whether WellPos is the last well on this type of plate

advance(order: Literal['row', 'col'] = 'col') WellPos[source]#

Advances to the “next” well position. Default is column-major order, i.e., A1, B1, C1, D1, E1, F1, G1, H1, A2, B2, … To switch to row-major order, select order as ‘row’, i.e., A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, B1, B2, …

Returns:

new WellPos representing the next well position

class riverine.Mix(*args, **kwargs)[source]#

Bases: riverine.components.AbstractComponent

Class denoting a Mix, a collection of source components mixed to some volume or concentration.

__hash__#
actions: riverine.units.Sequence[riverine.actions.AbstractAction]#
name: str = ''#

Name of the component.

test_tube_name: str | None#

A short name, eg, for labelling a test tube.

fixed_concentration: str | riverine.units.DecimalQuantity | None#
reference: riverine.references.Reference | None = None#
min_volume: riverine.units.DecimalQuantity#
plate: str | None#
well: riverine.locations.WellPos | None#
property is_mix: bool#
property fixed_total_volume: riverine.units.DecimalQuantity#
property buffer_name: str#
__eq__(other: object) bool[source]#
__attrs_post_init__() None[source]#
printed_name(tablefmt: str | tabulate.TableFormat) str[source]#
property concentration: riverine.units.DecimalQuantity#

Effective concentration of the mix. Calculated in order:

  1. If the mix has a fixed concentration, then that concentration.

  2. If fixed_concentration is a string, then the final concentration of the component with that name.

  3. If fixed_concentration is none, then the final concentration of the first mix component.

_get_concentration(_cache_key=None) riverine.units.DecimalQuantity[source]#
property total_volume: riverine.units.DecimalQuantity#

Total volume of the mix. If the mix has a fixed total volume, then that, otherwise, the sum of the transfer volumes of each component.

_get_total_volume(_cache_key=None) riverine.units.DecimalQuantity[source]#
property buffer_volume: riverine.units.Quantity#

The volume of buffer to be added to the mix, in addition to the components.

_get_buffer_volume(_cache_key=None) riverine.units.Quantity[source]#
table(tablefmt: tabulate.TableFormat | str = 'pipe', raise_failed_validation: bool = False, stralign='default', missingval='', showindex='default', disable_numparse=False, colalign=None, _cache_key=None) str[source]#

Generate a table describing the mix.

Parameters:
  • tablefmt – The output format for the table.

  • validate – Ensure volumes make sense.

mixlines(tablefmt: str | tabulate.TableFormat = 'pipe', _cache_key=None) list[riverine.printing.MixLine][source]#
has_fixed_concentration_action() bool[source]#
has_fixed_total_volume() bool[source]#
validate(tablefmt: str | tabulate.TableFormat | None = None, mixlines: riverine.units.Sequence[riverine.printing.MixLine] | None = None, raise_errors: bool = False, _cache_key=None) list[riverine.units.VolumeError][source]#
all_components_polars(_cache_key=None) polars.DataFrame[source]#
all_components() pandas.DataFrame[source]#

Return a Series of all component names, and their concentrations (as pint nM).

_repr_markdown_() str[source]#
_repr_html_() str[source]#
infoline(_cache_key=None) str[source]#
__repr__() str[source]#
__str__() str[source]#
with_experiment(experiment: riverine.experiments.Experiment, *, inplace: bool = True) Mix[source]#
with_reference(reference: riverine.references.Reference, *, inplace: bool = True) Mix[source]#
property location: tuple[str, riverine.locations.WellPos | None]#
vol_to_tube_names(tablefmt: str | tabulate.TableFormat = 'pipe', validate: bool = True) dict[riverine.units.DecimalQuantity, list[str]][source]#
Returns:

dict mapping a volume vol to a list of names of strands in this mix that should be pipetted with volume vol

_tube_map_from_mixline(mixline: riverine.printing.MixLine) str[source]#
tubes_markdown(tablefmt: str | tabulate.TableFormat = 'pipe') str[source]#
Parameters:

tablefmt – table format (see PlateMap.to_table() for description)

Returns:

  • a Markdown (or other format according to tablefmt)

  • string indicating which strands in test tubes to pipette, grouped by the volume

  • of each

display_instructions(plate_type: riverine.locations.PlateType = PlateType.wells96, raise_failed_validation: bool = False, combine_plate_actions: bool = True, well_marker: None | str | Callable[[str], str] = None, title_level: Literal[1, 2, 3, 4, 5, 6] = 3, warn_unsupported_title_format: bool = True, tablefmt: str | tabulate.TableFormat = 'unsafehtml', include_plate_maps: bool = True) None[source]#

Displays in a Jupyter notebook the result of calling Mix.instructions().

Parameters:
  • plate_type – 96-well or 384-well plate; default is 96-well.

  • raise_failed_validation – If validation fails (volumes don’t make sense), raise an exception.

  • combine_plate_actions – If True, then if multiple actions in the Mix take the same volume from the same plate, they will be combined into a single PlateMap.

  • well_marker – By default the strand’s name is put in the relevant plate entry. If well_marker is specified and is a string, then that string is put into every well with a strand in the plate map instead. This is useful for printing plate maps that just put, for instance, an ‘X’ in the well to pipette (e.g., specify well_marker='X'), e.g., for experimental mixes that use only some strands in the plate. To enable the string to depend on the well position (instead of being the same string in every well), well_marker can also be a function that takes as input a string representing the well (such as "B3" or "E11"), and outputs a string. For example, giving the identity function mix.to_table(well_marker=lambda x: x) puts the well address itself in the well.

  • title_level – The “title” is the first line of the returned string, which contains the plate’s name and volume to pipette. The title_level controls the size, with 1 being the largest size, (header level 1, e.g., # title in Markdown or <h1>title</h1> in HTML).

  • warn_unsupported_title_format – If True, prints a warning if tablefmt is a currently unsupported option for the title. The currently supported formats for the title are ‘github’, ‘html’, ‘unsafehtml’, ‘rst’, ‘latex’, ‘latex_raw’, ‘latex_booktabs’, “latex_longtable”. If tablefmt is another valid option, then the title will be the Markdown format, i.e., same as for tablefmt = ‘github’.

  • tablefmt – By default set to ‘github’ to create a Markdown table. For other options see astanin/python-tabulate

  • include_plate_maps – If True, include plate maps as part of displayed instructions, otherwise only include the more compact mixing table (which is always displayed regardless of this parameter).

Returns:

generate_picklist(experiment: riverine.experiments.Experiment | None, _cache_key=None) Mix.generate_picklist.PickList | None[source]#
Parameters:

experiment – experiment to use for generating picklist

Return type:

picklist for the mix

instructions(*, plate_type: riverine.locations.PlateType = PlateType.wells96, raise_failed_validation: bool = False, combine_plate_actions: bool = True, well_marker: None | str | Callable[[str], str] = None, title_level: Literal[1, 2, 3, 4, 5, 6] = 3, warn_unsupported_title_format: bool = True, tablefmt: str | tabulate.TableFormat = 'pipe', include_plate_maps: bool = True) str[source]#

Returns string combiniing the string results of calling Mix.table() and Mix.plate_maps() (then calling PlateMap.to_table() on each PlateMap).

Parameters:

plate_type – 96-well or 384-well plate; default is 96-well.

raise_failed_validation:

If validation fails (volumes don’t make sense), raise an exception.

combine_plate_actions:

If True, then if multiple actions in the Mix take the same volume from the same plate, they will be combined into a single PlateMap.

well_marker:

By default the strand’s name is put in the relevant plate entry. If well_marker is specified and is a string, then that string is put into every well with a strand in the plate map instead. This is useful for printing plate maps that just put, for instance, an ‘X’ in the well to pipette (e.g., specify well_marker='X'), e.g., for experimental mixes that use only some strands in the plate. To enable the string to depend on the well position (instead of being the same string in every well), well_marker can also be a function that takes as input a string representing the well (such as "B3" or "E11"), and outputs a string. For example, giving the identity function mix.to_table(well_marker=lambda x: x) puts the well address itself in the well.

title_level:

The “title” is the first line of the returned string, which contains the plate’s name and volume to pipette. The title_level controls the size, with 1 being the largest size, (header level 1, e.g., # title in Markdown or <h1>title</h1> in HTML).

warn_unsupported_title_format:

If True, prints a warning if tablefmt is a currently unsupported option for the title. The currently supported formats for the title are ‘github’, ‘html’, ‘unsafehtml’, ‘rst’, ‘latex’, ‘latex_raw’, ‘latex_booktabs’, “latex_longtable”. If tablefmt is another valid option, then the title will be the Markdown format, i.e., same as for tablefmt = ‘github’.

tablefmt:

By default set to ‘github’ to create a Markdown table. For other options see astanin/python-tabulate

include_plate_maps:

If True, include plate maps as part of displayed instructions, otherwise only include the more compact mixing table (which is always displayed regardless of this parameter).

Returns:

plate_maps(plate_type: riverine.locations.PlateType = PlateType.wells96, validate: bool = True, combine_plate_actions: bool = True) list[PlateMap][source]#

Similar to table(), but indicates only the strands to mix from each plate, in the form of a PlateMap.

NOTE: this ignores any strands in the Mix that are in test tubes. To get a list of strand names in test tubes, call Mix.vol_to_tube_names() or Mix.tubes_markdown().

By calling PlateMap.to_markdown() on each plate map, one can create a Markdown representation of each plate map, for example,

plate 1, 5 uL each
|     | 1    | 2      | 3      | 4    | 5        | 6   | 7   | 8   | 9   | 10   | 11   | 12   |
|-----|------|--------|--------|------|----------|-----|-----|-----|-----|------|------|------|
| A   | mon0 | mon0_F |        | adp0 |          |     |     |     |     |      |      |      |
| B   | mon1 | mon1_Q | mon1_F | adp1 | adp_sst1 |     |     |     |     |      |      |      |
| C   | mon2 | mon2_F | mon2_Q | adp2 | adp_sst2 |     |     |     |     |      |      |      |
| D   | mon3 | mon3_Q | mon3_F | adp3 | adp_sst3 |     |     |     |     |      |      |      |
| E   | mon4 |        | mon4_Q | adp4 | adp_sst4 |     |     |     |     |      |      |      |
| F   |      |        |        | adp5 |          |     |     |     |     |      |      |      |
| G   |      |        |        |      |          |     |     |     |     |      |      |      |
| H   |      |        |        |      |          |     |     |     |     |      |      |      |

or, with the well_marker parameter of PlateMap.to_markdown() set to 'X', for instance (in case you don’t need to see the strand names and just want to see which wells are marked):

plate 1, 5 uL each
|     | 1   | 2   | 3   | 4   | 5   | 6   | 7   | 8   | 9   | 10   | 11   | 12   |
|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|------|------|------|
| A   | *   | *   |     | *   |     |     |     |     |     |      |      |      |
| B   | *   | *   | *   | *   | *   |     |     |     |     |      |      |      |
| C   | *   | *   | *   | *   | *   |     |     |     |     |      |      |      |
| D   | *   | *   | *   | *   | *   |     |     |     |     |      |      |      |
| E   | *   |     | *   | *   | *   |     |     |     |     |      |      |      |
| F   |     |     |     | *   |     |     |     |     |     |      |      |      |
| G   |     |     |     |     |     |     |     |     |     |      |      |      |
| H   |     |     |     |     |     |     |     |     |     |      |      |      |
Parameters:
  • plate_type – 96-well or 384-well plate; default is 96-well.

  • validate – Ensure volumes make sense.

  • combine_plate_actions – If True, then if multiple actions in the Mix take the same volume from the same plate, they will be combined into a single PlateMap.

Return type:

A list of all plate maps.

_plate_map_from_mixline(mixline: riverine.printing.MixLine, plate_type: riverine.locations.PlateType, existing_plate_map: PlateMap | None) PlateMap[source]#
_update_volumes(consumed_volumes: dict[str, riverine.units.Quantity] | None = None, made_volumes: dict[str, riverine.units.Quantity] | None = None, _cache_key=None) Tuple[dict[str, riverine.units.Quantity], dict[str, riverine.units.Quantity]][source]#

Given a

_unstructure(experiment: riverine.experiments.Experiment | None = None) dict[str, Any][source]#
classmethod _structure(d: dict[str, Any], experiment: riverine.experiments.Experiment | None = None) Mix[source]#
class riverine.MixLine[source]#

Class for handling a line of a (processed) mix recipe.

Each line should represent a single step, or series of similar steps (same volume per substep) in the mixing process.

Parameters:
  • names – A list of component names. For a single step, use [name].

  • source_conc – The source concentration; may not be provided (will be left blank), or be a descriptive string.

  • dest_conc – The destination/target concentration; may not be provided (will be left blank), or be a descriptive string.

  • total_tx_vol – The total volume added to the mix by the step. If zero, the amount will still be included in tables. If None, the amount will be blank. If provided, and the line is not fake, the value must be correct and interpretable for calculations involving the mix.

  • number – The number of components added / subste

  • each_tx_vol – The volume per component / substep. May be omitted, or a descriptive string.

  • plate – The plate name for the mix, a descriptive string for location / source type (eg, “tube”) or None (omitted). A single MixLine, at present, should not involve multiple plates.

  • wells – A list of wells for the components in a plate. If the components are not in a plate, this must be an empty list. This does not parse strings; wells must be provided as WellPos instances.

  • note – A note to add for the line

  • fake – Denotes that the line is not a real step, eg, for a summary/total information line. The line will be distinguished in some way in tables (eg, italics) and will not be included in calculations.

names: list[str]#
source_conc: riverine.units.DecimalQuantity | str | None = None#
dest_conc: riverine.units.DecimalQuantity | str | None = None#
total_tx_vol: riverine.units.DecimalQuantity#
number: int = 1#
each_tx_vol: riverine.units.DecimalQuantity#
plate: str = ''#
wells: list[riverine.locations.WellPos]#
note: str | None = None#
fake: bool = False#
__attrs_post_init__()[source]#
_check_wells(_: str, v: Any) None[source]#
_check_names(_: str, v: Any) None[source]#
location(tablefmt: str | tabulate.TableFormat = 'pipe', split: bool = True) tuple[str | list[str], list[int]][source]#

A formatted string (according to tablefmt) for the location of the component/components.

toline(incea: bool, tablefmt: str | tabulate.TableFormat = 'pipe') riverine.units.Sequence[str][source]#
riverine.master_mix(mixes: Iterable[Mix], name: str = 'master mix', excess: float | riverine.units.Decimal = Decimal(0.05), exclude_shared_components: Iterable[str | riverine.components.Component] = ()) tuple[Mix, list[Mix]][source]#

Create a “master mix” useful for saving pipetting steps when creating Mix’s in mixes by grouping components shared among each Mix’s in mixes into a single large master mix from which the shared components can be pipetted to create the downstream mixes.

Components are considered “shared” if they appear in all Mix’s in mixes.

To ensure sufficient volume for the last mix when the number of mixes is large (due to slight pipetting error from the master mix adding up over many steps), the parameter excess can be used to control how much of a slight excess of necessary volume is included in the master mix.

Shared Components may be excluded from the master mix by putting them or their names in the parameter exclude_shared_components.

Example:

# staple mix to be shared in all mixes
staples = [Strand(f"stap{i}", concentration="1uM") for i in range(5)]
staple_mix = Mix(
    actions=[FixedConcentration(components=staples, fixed_concentration="100 nM")],
    name="staple mix",
)

# "adapter" mixes that are different between mixes
num_variants = 3
adapter_mixes = {}
for adp_idx in range(num_variants):
    adapters = [Strand(f'adp_{adp_idx}_{i}', concentration="1uM") for i in range(5)]
    adapter_mix = Mix(
        actions=[FixedConcentration(components=adapters, fixed_concentration="50 nM")],
        name=f"adapters {adp_idx} mix",
    )
    adapter_mixes[adp_idx] = adapter_mix

m13 = Strand("m13 100nM", concentration="100 nM")
mixes = [Mix(
    actions=[
        FixedConcentration(components=[m13], fixed_concentration=f"1 nM"),
        FixedConcentration(components=[staple_mix], fixed_concentration=f"10 nM"),
        FixedConcentration(components=[adapter_mixes[adp_idx]], fixed_concentration=f"10 nM"),
    ],
    name="mm",
    fixed_total_volume=f"100 uL",
) for adp_idx, adapter_mix in adapter_mixes.items()]
mm, final_mixes = master_mix(mixes=mixes, name='origami master mix', excess=0.1)

print(mm.instructions())
for mix in final_mixes:
    print(mix.instructions())

This should print the following. Note that only 63 uL of master mix are strictly required, but the total master mix volume is 10% higher (69.3 uL) due to the parameter excess = 0.1.

## Mix "origami master mix":
| Component   | [Src]     | [Dest]     | #   | Ea Tx Vol   | Tot Tx Vol   | Location  | Note  |
|:------------|:----------|:-----------|:----|:------------|:-------------|:----------|:------|
| staple mix  | 100.00 nM | 47.62 nM   |     | 33.00 µl    | 33.00 µl     |           |       |
| m13 100nM   | 100.00 nM | 4.76 nM    |     | 3.30 µl     | 3.30 µl      |           |       |
| 10x buffer  | 100.00 mM | 47.62 mM   |     | 33.00 µl    | 33.00 µl     |           |       |
| Buffer      |           |            |     | 0.00 µl     | 0.00 µl      |           |       |
| *Total:*    |           | *47.62 nM* | *4* |             | *69.30 µl*   |           |       |

Aliquot 21.00 µl from this mix into 3 different test tubes.

## Mix "mix0":
| Component          | [Src]     | [Dest]     | #   | Ea Tx Vol   | Tot Tx Vol   | Location  | Note  |
|:-------------------|:----------|:-----------|:----|:------------|:-------------|:----------|:------|
| origami master mix | 47.62 nM  | 10.00 nM   |     | 21.00 µl    | 21.00 µl     |           |       |
| Mg++               | 125.00 mM | 12.50 mM   |     | 10.00 µl    | 10.00 µl     |           |       |
| adapters 0 mix     | 50.00 nM  | 20.00 nM   |     | 40.00 µl    | 40.00 µl     |           |       |
| Buffer             |           |            |     | 29.00 µl    | 29.00 µl     |           |       |
| *Total:*           |           | *10.00 nM* | *4* |             | *100.00 µl*  |           |       |

## Mix "mix1":
| Component          | [Src]     | [Dest]     | #   | Ea Tx Vol   | Tot Tx Vol   | Location  | Note  |
|:-------------------|:----------|:-----------|:----|:------------|:-------------|:----------|:------|
| origami master mix | 47.62 nM  | 10.00 nM   |     | 21.00 µl    | 21.00 µl     |           |       |
| Mg++               | 125.00 mM | 12.50 mM   |     | 10.00 µl    | 10.00 µl     |           |       |
| adapters 1 mix     | 55.00 nM  | 20.00 nM   |     | 36.36 µl    | 36.36 µl     |           |       |
| Buffer             |           |            |     | 32.64 µl    | 32.64 µl     |           |       |
| *Total:*           |           | *10.00 nM* | *4* |             | *100.00 µl*  |           |       |

## Mix "mix2":
| Component          | [Src]     | [Dest]     | #   | Ea Tx Vol   | Tot Tx Vol   | Location  | Note  |
|:-------------------|:----------|:-----------|:----|:------------|:-------------|:----------|:------|
| origami master mix | 47.62 nM  | 10.00 nM   |     | 21.00 µl    | 21.00 µl     |           |       |
| Mg++               | 125.00 mM | 12.50 mM   |     | 10.00 µl    | 10.00 µl     |           |       |
| adapters 2 mix     | 60.00 nM  | 20.00 nM   |     | 33.33 µl    | 33.33 µl     |           |       |
| Buffer             |           |            |     | 35.67 µl    | 35.67 µl     |           |       |
| *Total:*           |           | *10.00 nM* | *4* |             | *100.00 µl*  |           |       |
Parameters:
  • mixes – the list of Mix’s of which to calculate a shared master mix

  • name – name of the master mix

  • excess – fraction of “excess” volume to include in master mix to ensure sufficient volume in all downstream mixes; see parameter excess of split_mix() for explanation

  • exclude_shared_components – names of shared components (or Components themselves) to exclude from master mix; raises exception if any element of exclude_shared_components is not shared by all Mix’s in the parameter mixes

Returns:

  • pair (master_mix, final_mixes), where master_mix is the master mix to use in

  • downstream final_mixes. Length of final_mixes is the same as parameter mixes, and

  • they use the same names, but each Mix in final_mixes will be created by a single

  • pipetting step from master_mix rather than individual pipetting steps for each shared component.

riverine.split_mix(mix: Mix, num_tubes: int | None = None, names: Iterable[str] | None = None, excess: float | riverine.units.Decimal = Decimal(0.05)) Mix[source]#

A “split mix” is a Mix that involves creating a large volume mix and splitting it into several test tubes with identical contents. The advantage of specifying a split mix is that one can give the desired volumes/concentrations in the individual test tubes (post splitting) and the number of test tubes, and the correct amounts in the larger mix will automatically be calculated.

The Mix.instructions() method of a split mix includes the additional instruction at the end to aliquot from the larger mix.

Parameters:
  • mix – The Mix object describing what each individual smaller test tube should contain after the split.

  • num_tubes – The number of test tubes into which to split the large mix. Should not be specified if names is specified; in that case num_tubes is assumed to be the number of strings in names.

  • excess

    A fraction (between 0 and 1) indicating how much extra of the large mix to make. This is useful when num_tubes is large, since the aliquots prior to the last test tube may take a small amount of extra volume, resulting in the final test tube receiving significantly less volume if the large mix contained only just enough total volume.

    For example, if the total volume is 100 uL and num_tubes is 20, then each aliquot from the large mix to test tubes would be 100/20 = 5 uL. But if due to pipetting imprecision 5.05 uL is actually taken, then the first 19 aliquots will total to 19*5.05 = 95.95 uL, so there will only be 100 - 95.95 = 4.05 uL left for the last test tube. But by setting excess to 0.05, then to make 20 test tubes of 5 uL each, we would have 5*20*1.05 = 105 uL total, and in this case even assuming pipetting error resulting in taking 95.95 uL for the first 19 samples, there is still 105 - 95.95 = 9.05 uL left, more than enough for the 20’th test tube.

    Note: using excess > 0 means than the test tube with the large mix should not be reused as one of the final test tubes, since it will have too much volume at the end.

  • names – Names of smaller individual test tubes (will be printed in instructions).

Returns:

  • A “large” mix, from which num_tubes aliquots can be made to create each of the identical

  • ”small” mixes.

riverine.hydrate_and_measure_conc_and_dilute(nmol: float | str | riverine.units.DecimalQuantity, target_conc_high: float | str | riverine.units.DecimalQuantity, target_conc_low: float | str | riverine.units.DecimalQuantity, absorbance: float | Sequence[float], ext_coef: float, vol_removed: None | float | str | riverine.units.DecimalQuantity = None) tuple[riverine.units.DecimalQuantity, riverine.units.DecimalQuantity][source]#

Assuming hydrate() is called with parameters nmol and target_conc_high to give initial volumes to add to a dry sample to reach a “high” concentration target_conc_high, and assuming absorbances are then measured, calculates subsequent dilution volumes to reach “low” concentration target_conc_low, and also actual “start” concentration (i.e., actual concentration after adding initial hydration that targeted target_conc_high, according to absorbance).

This is on the assumption that the first hydration step could result in a concentration below target_conc_high, so target_conc_high should be chosen sufficiently larger than target_conc_low so that the actual measured concentration after the first step is likely to be above target_conc_low, so that it is possible to reach concentration target_conc_low with a subsequent dilution step. (As opposed to requiring a vacufuge to concentrate the sample higher).

Parameters:
  • nmol – number of nmol (nanomoles) of dry product.

  • target_conc_high – target concentration for initial hydration. Should be higher than target_conc_low,

  • target_conc_low – the “real” target concentration that we will try to hit after the second addition of water/buffer.

  • absorbance – UV absorbance at 260 nm. Can either be a single float/int or a nonempty sequence of floats/ints representing repeated measurements; if the latter then an average is taken.

  • ext_coef – Extinction coefficient in L/mol*cm.

  • vol_removed – Total volume removed from vol to measure absorbance. For example, if two samples were taken, one at 1 µL and one at 1.5 µL, then set vol_removed = 2.5 µL. If not specified, it is assumed that each sample is 1 µL, and that the total number of samples taken is the number of entries in absorbance. If absorbance is a single volume (e.g., float, int, str, DecimalQuantity), then it is assumed the number of samples is 1 (i.e., vol_removed = 1 µL), otherwise if absorbance is a list, then the length of the list is assumed to be the number of samples taken, each at 1 µL.

:param : The pair (current concentration of DNA sample, volume to add to reach target_conc) :type : return:

riverine.measure_conc_and_dilute(absorbance: float | Sequence[float], ext_coef: float, target_conc: float | str | riverine.units.DecimalQuantity, vol: float | str | riverine.units.DecimalQuantity, vol_removed: None | float | str | riverine.units.DecimalQuantity = None) tuple[riverine.units.DecimalQuantity, riverine.units.DecimalQuantity][source]#

Calculates concentration of DNA sample given an absorbance reading on a NanoDrop machine, then calculates the amount of buffer/water that must be added to dilute it to a target concentration.

Parameters:
  • absorbance – UV absorbance at 260 nm. Can either be a single float/int or a nonempty sequence of floats/ints representing repeated measurements; if the latter then an average is taken.

  • ext_coef – Extinction coefficient in L/mol*cm.

  • target_conc – target concentration. If float/int, units are µM (micromolar).

  • vol – current volume of sample. If float/int, units are µL (microliters) NOTE: This is the volume before samples are taken to measure absorbance. It is assumed that each sample taken to measure absorbance is 1 µL. If that is not the case, then set the parameter vol_removed to the total volume removed.

  • vol_removed – Total volume removed from vol to measure absorbance. For example, if two samples were taken, one at 1 µL and one at 1.5 µL, then set vol_removed = 2.5 µL. If not specified, it is assumed that each sample is 1 µL, and that the total number of samples taken is the number of entries in absorbance. If absorbance is a single volume (e.g., float, int, str, DecimalQuantity), then it is assumed the number of samples is 1 (i.e., vol_removed = 1 µL), otherwise if absorbance is a list, then the length of the list is assumed to be the number of samples taken, each at 1 µL.

Return type:

The pair (current concentration of DNA sample, volume to add to reach target_conc)

class riverine.Reference[source]#
df: pandas.DataFrame#
property loc: pandas.core.indexing._LocIndexer#
__getitem__(key: Any) Any[source]#
__eq__(other: object) bool[source]#
__len__() int[source]#
plate_map(name: str, plate_type: riverine.locations.PlateType = PlateType.wells96) riverine.mixes.PlateMap[source]#

Return a PlateMap for a given plate name in the Reference.

Parameters:
  • name – Name of plate to make a PlateMap for.

  • plate_type – Either PlateType.wells96 or PlateType.wells384; default is PlateType.wells96.

Returns:

  • a PlateMap consisting of all strands in this Reference object from plate named

  • name. Currently always makes a 96-well plate.

Raises:

ValueError: – If name is not the name of a plate in the reference.

search(name: str | None = None, plate: str | None = None, well: str | riverine.locations.WellPos | None = None, concentration: str | riverine.units.DecimalQuantity | None = None, sequence: str | None = None) Reference[source]#
get_concentration(name: str | None = None, plate: str | None = None, well: str | riverine.locations.WellPos | None = None, concentration: str | riverine.units.DecimalQuantity | None = None, sequence: str | None = None) riverine.units.DecimalQuantity[source]#
classmethod from_csv(filename_or_file: str | TextIO | os.PathLike[str]) Reference[source]#

Load reference information from a CSV file.

The reference information loaded by this function should be compiled manually, fitting the mix reference format, or be loaded with compile_reference() or update_reference().

to_csv(filename: str | os.PathLike[str]) None[source]#
update(files: Sequence[RefFile] | RefFile, round: int = -1) Reference[source]#

Update reference information.

This updates an existing reference dataframe with new files, with the same methods as compile_reference().

classmethod compile(files: Sequence[RefFile] | RefFile, round: int = -1) Reference[source]#

Compile reference information.

This loads information from the following sources:

  • An IDT plate order spreadsheet. This does not include concentration. To add concentration information, list it as a tuple of

(file, concentration). - An IDT bulk order entry text file. - An IDT plate spec sheet.

riverine.load_reference(filename_or_file: str | TextIO) Reference[source]#
riverine.DNAN[source]#
riverine.Q_(qty: int | str | decimal.Decimal | float, unit: str | pint.Unit | pint.facets.plain.PlainUnit | pint.Quantity | None = None) DecimalQuantity[source]#

Convenient constructor for units, eg, Q_(5.0, 'nM'). Ensures that the quantity is a Decimal.

exception riverine.VolumeError[source]#

Bases: ValueError

Inappropriate argument value (of correct type).

riverine.nM[source]#
riverine.uL[source]#
riverine.uM[source]#
riverine.ureg[source]#
riverine.html_with_borders_tablefmt[source]#

Pass this as the parameter tablefmt in any method that accepts that parameter to have the table be an HTML table with borders around each cell.