AFL.automation.mixcalc#

Classes

BalanceDiagnosis(success, details, ...)

Full diagnosis of a single balance result.

Component(name[, mass, volume, density, ...])

Component of a mixture

Context(name)

Inherited by Pipeline to allow for context manager abuse

FailureCode(value)

Machine-readable codes describing why a mass balance failed.

FailureDetail(code, description, ...)

One specific failure mode detected during diagnosis.

MassBalance([name, minimum_volume])

MassBalanceBase()

MassBalanceDriver([overrides])

MassBalanceWebAppMixin()

MixDB([db_spec])

PipetteAction(source, dest, volume[, ...])

Solution(name[, total_mass, total_volume, ...])

TargetSolution(name[, total_mass, ...])

Exceptions

class AFL.automation.mixcalc.BalanceDiagnosis(success: bool, details: ~typing.List[~AFL.automation.mixcalc.BalanceDiagnosis.FailureDetail] = <factory>, component_errors: ~typing.Dict[str, float] = <factory>)[source]#

Full diagnosis of a single balance result.

__init__(success: bool, details: ~typing.List[~AFL.automation.mixcalc.BalanceDiagnosis.FailureDetail] = <factory>, component_errors: ~typing.Dict[str, float] = <factory>) None#
summary() str[source]#

Return a human-readable failure summary.

to_dict() Dict[str, Any][source]#
success: bool#
details: List[FailureDetail]#
component_errors: Dict[str, float]#
class AFL.automation.mixcalc.FailureCode(value)[source]#

Machine-readable codes describing why a mass balance failed.

Codes are ordered from specific root causes to general symptoms so that the most actionable information appears first.

MISSING_STOCK_COMPONENT = 'missing_stock_component'#
STOCK_CONCENTRATION_TOO_LOW = 'stock_concentration_too_low'#
TARGET_OUTSIDE_REACHABLE_COMPOSITIONS = 'target_outside_reachable_compositions'#
BELOW_MINIMUM_PIPETTE_VOLUME = 'below_minimum_pipette_volume'#
UNWANTED_STOCK_COMPONENT = 'unwanted_stock_component'#
TOLERANCE_EXCEEDED = 'tolerance_exceeded'#
class AFL.automation.mixcalc.FailureDetail(code: ~AFL.automation.mixcalc.BalanceDiagnosis.FailureCode, description: str, affected_components: ~typing.List[str] = <factory>, affected_stocks: ~typing.List[str] = <factory>, data: ~typing.Dict[str, ~typing.Any] = <factory>)[source]#

One specific failure mode detected during diagnosis.

__init__(code: ~AFL.automation.mixcalc.BalanceDiagnosis.FailureCode, description: str, affected_components: ~typing.List[str] = <factory>, affected_stocks: ~typing.List[str] = <factory>, data: ~typing.Dict[str, ~typing.Any] = <factory>) None#
to_dict() Dict[str, Any][source]#
code: FailureCode#
description: str#
affected_components: List[str]#
affected_stocks: List[str]#
data: Dict[str, Any]#
class AFL.automation.mixcalc.Component(name: str, mass: Quantity | None = None, volume: Quantity | None = None, density: Quantity | None = None, formula: str | None = None, sld: Quantity | None = None, uid: str | None = None, solute: bool = False)[source]#

Component of a mixture

This class defines the basic properties of a component within a mixture. It includes attributes for mass, volume, density, formula, and scattering length density (SLD). It also enforces unit specifications for these attributes.

Parameters:
  • name (str) – The name of the component.

  • mass (str | units.Quantity | None) – The mass of the component, by default None.

  • volume (str | units.Quantity | None) – The volume of the component, by default None.

  • density (str | units.Quantity | None) – The density of the component, by default None.

  • formula (Optional[str], optional) – The chemical formula of the component, by default None.

  • sld (str | units.Quantity | None) – The scattering length density of the component, by default None.

__hash__() int[source]#

Needed so Components can be dictionary keys

__init__(name: str, mass: Quantity | None = None, volume: Quantity | None = None, density: Quantity | None = None, formula: str | None = None, sld: Quantity | None = None, uid: str | None = None, solute: bool = False) None[source]#
__iter__() Iterator[Tuple[str, Component]][source]#

Dummy iterator to mimic behavior of Mixture.

copy() Component[source]#
property density: Quantity | None#
emit() Dict[str, str | Quantity][source]#
property formula: formula | None#
property has_density: bool#
property has_formula: bool#
property has_mass: bool#
property has_sld: bool#
property has_volume: bool#
property is_solute: bool#
property is_solvent: bool#
property mass: Quantity | None#
property moles: Quantity | None#
set_mass(value: Quantity) Component[source]#

Setter for inline mass changes

set_volume(value: Quantity) Component[source]#

Setter for inline volume changes

property sld: Quantity | None#
property volume: Quantity | None#
class AFL.automation.mixcalc.Context(name)[source]#

Inherited by Pipeline to allow for context manager abuse

See https://stackoverflow.com/questions/49573131/how-are-pymc3-variables-assigned-to-the-currently-active-model

__init__(name)[source]#
add_self_to_context(stack_name=None)[source]#
contexts = <_thread._local object>#
classmethod get_context() Any[source]#

Return the deepest context on the stack.

classmethod get_contexts() List[source]#
exception AFL.automation.mixcalc.NoContextException[source]#
class AFL.automation.mixcalc.MassBalance(name='MassBalance', minimum_volume='20 ul')[source]#
__init__(name='MassBalance', minimum_volume='20 ul')[source]#
property stock_components: Set[str]#
property target_components: Set[str]#
class AFL.automation.mixcalc.MassBalanceBase[source]#
__init__()[source]#
balance(tol=0.05, return_report=False, progress_callback: Callable[[...], Any] | None = None, enable_multistep_dilution: bool = False, multistep_max_steps: int = 2, multistep_diluent_policy: str = 'primary_solvent')[source]#
balance_report()[source]#

Returns a json serializable structure that has all of the balanced targets that can be reconstituted by the user back into solution objects.

property components: Set[str]#
failure_summary() str[source]#

Return a human-readable summary of all failed balance entries.

Returns an empty string if all balances succeeded or no balances have been run yet.

make_target_names(n_letters: int = 2, components=None, name_map: Dict | None = None)[source]#
mass_fraction_matrix() ndarray[source]#
property stock_components: Set[str]#
property target_components: Set[str]#
class AFL.automation.mixcalc.MassBalanceDriver(overrides=None)[source]#
__init__(overrides=None)[source]#
add_component(**component)[source]#
add_stock(solution: Dict, reset: bool = False)[source]#
add_target(target: Dict, reset: bool = False)[source]#
add_targets(targets: List[Dict], reset: bool = False)[source]#
balance(return_report=False, enable_multistep_dilution=None)[source]#
compute_stock_properties(stock=None, **kwargs)[source]#
defaults = {'enable_multistep_dilution': False, 'minimum_volume': '20 ul', 'multistep_diluent_policy': 'primary_solvent', 'multistep_max_steps': 2, 'orchestrator_uri': '', 'orchestrator_username': 'Orchestrator', 'prepare_uri': '', 'prepare_username': 'Prepare', 'stock_history': [], 'stocks': [], 'sweep_config': {}, 'targets': [], 'tol': 0.001}#
get_balance_progress()[source]#
get_balance_settings()[source]#
get_sample_composition(composition_format='mass_fraction')[source]#

Get the composition of the last balanced target in the requested format.

Uses the Solution objects in self.balanced which have full access to the component database, avoiding the need for the caller to reconstruct Solution objects.

Parameters:

composition_format (str or dict) – If str, a single format applied to all components. If dict, maps component names to format strings; components not listed default to 'mass_fraction'. Valid formats: 'mass_fraction', 'volume_fraction', 'concentration', 'molarity'.

Returns:

Composition dictionary with component names as keys and numeric values in the requested format.

Return type:

dict

get_storage_sources()[source]#
list_balanced_targets()[source]#
list_components()[source]#
list_stock_history()[source]#
list_stocks()[source]#
list_targets()[source]#
load_stock_history(snapshot_id=None)[source]#
load_sweep_config()[source]#
process_stocks()[source]#
process_targets()[source]#
remove_component(name=None, uid=None)[source]#
reset_stocks()[source]#
reset_targets()[source]#
save_sweep_config(sweep_config=None)[source]#
property stock_components#
property target_components#
update_component(**component)[source]#
upload_stocks(stocks=None, reset=True, tags=None)[source]#
upload_targets(targets=None, reset=True)[source]#
class AFL.automation.mixcalc.MassBalanceWebAppMixin[source]#
get_orchestrator_context(orchestrator_uri: str | None = None)[source]#
get_prepare_context(prepare_uri: str | None = None)[source]#
mixdoctor(**kwargs)[source]#
submit_orchestrator_grid(sample_mode: str = 'balanced_all', samples: List[Dict] | None = None, process_sample_kwargs: Dict | None = None, config_overrides: Dict | None = None, orchestrator_uri: str | None = None)[source]#
submit_prepare_grid(sample_mode: str = 'balanced_all', samples: List[Dict] | None = None, prepare_kwargs: Dict | None = None, config_overrides: Dict | None = None, prepare_uri: str | None = None)[source]#
class AFL.automation.mixcalc.MixDB(db_spec: str | Path | DataFrame | None = None)[source]#
__init__(db_spec: str | Path | DataFrame | None = None)[source]#
add_component(component_dict: Dict) str[source]#
add_component_interactive(name, uid=None)[source]#
get_component(name=None, uid=None, interactive=False)[source]#
static get_db()[source]#

Retrieve the global _MIXDB instance.

Raises:

ValueError – If _MIXDB is not set.

Returns:

The _MIXDB instance.

get_source() str[source]#
list_components()[source]#
remove_component(name=None, uid=None)[source]#
set_db()[source]#
update_component(component_dict: Dict) str[source]#
write()[source]#
class AFL.automation.mixcalc.PipetteAction(source, dest, volume, source_loc=None, dest_loc=None, aspirate_rate=None, dispense_rate=None, mix_aspirate_rate=None, mix_dispense_rate=None, mix_before=None, mix_after=None, blow_out=False, post_aspirate_delay=0.0, post_dispense_delay=0.0, aspirate_equilibration_delay=0.0, drop_tip=True, force_new_tip=False, to_top=True, to_center=False, to_top_z_offset=0, fast_mixing=False, touch_tip=False)[source]#
__init__(source, dest, volume, source_loc=None, dest_loc=None, aspirate_rate=None, dispense_rate=None, mix_aspirate_rate=None, mix_dispense_rate=None, mix_before=None, mix_after=None, blow_out=False, post_aspirate_delay=0.0, post_dispense_delay=0.0, aspirate_equilibration_delay=0.0, drop_tip=True, force_new_tip=False, to_top=True, to_center=False, to_top_z_offset=0, fast_mixing=False, touch_tip=False)[source]#
emit_protocol()[source]#
get_kwargs()[source]#
class AFL.automation.mixcalc.Solution(name: str, total_mass: str | Quantity | None = None, total_volume: str | Quantity | None = None, masses: Dict | None = None, volumes: Dict | None = None, concentrations: Dict | None = None, mass_fractions: Dict | None = None, volume_fractions: Dict | None = None, molarities: Dict | None = None, molalities: Dict | None = None, location: str | None = None, solutes: List[str] | None = None, sanity_check: bool | None = True)[source]#
__eq__(other)[source]#

Compare the mass,volume, and composition of two mixtures

__hash__()[source]#

Needed so Solutions can be dictionary keys

__init__(name: str, total_mass: str | Quantity | None = None, total_volume: str | Quantity | None = None, masses: Dict | None = None, volumes: Dict | None = None, concentrations: Dict | None = None, mass_fractions: Dict | None = None, volume_fractions: Dict | None = None, molarities: Dict | None = None, molalities: Dict | None = None, location: str | None = None, solutes: List[str] | None = None, sanity_check: bool | None = True)[source]#

Initialize a Solution object.

Parameters:
  • name (str) – The name of the solution.

  • total_mass (str or pint.Quantity, optional) – The total mass of the solution.

  • total_volume (str or pint.Quantity, optional) – The total volume of the solution.

  • masses (dict, optional) – A dictionary of component masses.

  • volumes (dict, optional) – A dictionary of component volumes.

  • concentrations (dict, optional) – A dictionary of component concentrations.

  • mass_fractions (dict, optional) – A dictionary of component mass fractions. A single component can have a value of None to indicate it should be calculated as the remainder (1.0 - sum of other fractions).

  • volume_fractions (dict, optional) – A dictionary of component volume fractions. A single component can have a value of None to indicate it should be calculated as the remainder (1.0 - sum of other fractions).

  • molarities (dict, optional) – A dictionary of component molarities (moles per liter of solution).

  • molalities (dict, optional) – A dictionary of component molalities (moles per kilogram of solvent).

  • location (str, optional) – The location of the solution on the robot. Usually a deck location e.g., ‘1A1’.

  • solutes (list of str, optional) – A list of solute names. If set, the components will be initialized as solutes and they won’t contribute to the volume of the solution

  • sanity_check (bool, optional) – Whether to perform a sanity check on the solution.

Raises:

ValueError – If concentrations are set without specifying a component with volume. If mass fractions are set without specifying a component with mass or the total mass. If volume fractions are set without specifying a component with volume or the total volume. If molarities are set without specifying a component with volume. If molalities are set without specifying a solvent with mass.

add_component(name, solutes: List[str] | None = None)[source]#
all_components_have_mass()[source]#
property concentration#
contains(name: str) bool[source]#
copy(name=None)[source]#
property mass: Quantity#

Total mass of mixture.

property mass_fraction#

Mass fraction of components in mixture

Returns:

  • mass_fraction (dict)

  • Component mass fractions

measure_out(amount: str | Quantity, deplete: object = False) Solution[source]#

Create solution with identical composition at new total mass/volume

property molality#

Molality of components in mixture (moles of solute per kilogram of solvent)

Returns:

molality – Component molalities for components with chemical formulas defined

Return type:

dict

property molarity#
rename_component(old_name, new_name, inplace=False)[source]#
set_mass(value: str | Quantity)[source]#

Setter for inline mass changes

set_properties_from_dict(properties=None, inplace=False)[source]#
set_volume(value: str | Quantity)[source]#

Setter for inline volume changes

property size#
property solutes#
property solvent_density#
property solvent_mass#
property solvent_sld: Quantity#
property solvent_volume#
property solvents#
to_dict()[source]#
property volume: Quantity#

Total volume of mixture. Only solvents are included in volume calculation

property volume_fraction#

Volume fraction of solvents in mixture

Returns:

  • solvent_fraction (dict)

  • Component mass fractions

class AFL.automation.mixcalc.TargetSolution(name: str, total_mass: str | Quantity | None = None, total_volume: str | Quantity | None = None, masses: Dict | None = None, volumes: Dict | None = None, concentrations: Dict | None = None, mass_fractions: Dict | None = None, volume_fractions: Dict | None = None, molarities: Dict | None = None, molalities: Dict | None = None, location: str | None = None, solutes: List[str] | None = None, sanity_check: bool | None = True)[source]#