riverine#
Submodules#
Attributes#
Pass this as the parameter tablefmt in any method that accepts that parameter to have the table |
Exceptions#
Inappropriate argument value (of correct type). |
Classes#
Abstract class defining an action in a mix recipe. |
|
An action adding an equal concentration of each component, without setting that concentration. |
|
An action adding one or multiple components, with a set destination concentration per component (adjusting volumes). |
|
An action adding one or multiple components, with a set transfer volume. |
|
Add an amount of (non-mix) components to result in a fixed total concentration of each in the mix. |
|
Abstract class defining an action in a mix recipe. |
|
Abstract class for a component in a mix. Custom components that don't inherit from |
|
A single named component, potentially with a concentration and location. |
|
A single named strand, potentially with a concentration, location and sequence. |
|
A class collecting many related mixes and components, allowing methods to be run that consider all of them |
|
A Well reference, allowing movement in various directions and bounds checking. |
|
Class denoting a Mix, a collection of source components mixed to |
|
Class for handling a line of a (processed) mix recipe. |
|
Functions#
|
Create a "master mix" useful for saving pipetting steps when creating |
|
A "split mix" is a |
Assuming |
|
Calculates concentration of DNA sample given an absorbance reading on a NanoDrop machine, |
|
|
|
|
Convenient constructor for units, eg, |
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.
- 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:
FixedVolumeAn 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:
ActionWithComponentsAn 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:
ActionWithComponentsAn 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#
- _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.ToConcentration[source]#
Bases:
ActionWithComponentsAdd 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:
ActionWithComponentsAbstract 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.ABCAbstract 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 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]#
- _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:
AbstractComponentA 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.
- 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]#
- _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:
ComponentA 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#
- 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]#
- __getitem__(name: str) riverine.components.AbstractComponent[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.
- 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#
- 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.
- 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.AbstractComponentClass 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#
- property concentration: riverine.units.DecimalQuantity#
Effective concentration of the mix. Calculated in order:
If the mix has a fixed concentration, then that concentration.
If fixed_concentration is a string, then the final concentration of the component with that name.
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.
- 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]#
- 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() pandas.DataFrame[source]#
Return a Series of all component names, and their concentrations (as pint nM).
- 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 functionmix.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:
pipetting instructions in the form of strings combining results of
Mix.table()and
- 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()andMix.plate_maps()(then callingPlateMap.to_table()on eachPlateMap).- 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 functionmix.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:
pipetting instructions in the form of strings combining results of
Mix.table()and
- 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 aPlateMap.NOTE: this ignores any strands in the
Mixthat are in test tubes. To get a list of strand names in test tubes, callMix.vol_to_tube_names()orMix.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#
- 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 eachMix’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 mixname – 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 explanationexclude_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
Mixin final_mixes will be created by a singlepipetting 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
Mixthat 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
Mixobject 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#
- plate_map(name: str, plate_type: riverine.locations.PlateType = PlateType.wells96) riverine.mixes.PlateMap[source]#
Return a
PlateMapfor a given plate name in the Reference.- Parameters:
name – Name of plate to make a
PlateMapfor.plate_type – Either
PlateType.wells96orPlateType.wells384; default isPlateType.wells96.
- Returns:
a
PlateMapconsisting of all strands in this Reference object from plate namedname. 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()orupdate_reference().
- 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.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.