Пример #1
0
def reaction() -> reaction_pb2.Reaction:
    resolver = units.UnitResolver()
    reaction = reaction_pb2.Reaction()
    reaction.setup.is_automated = True
    reaction.inputs["dummy_input"].components.add().CopyFrom(
        message_helpers.build_compound(
            name="n-hexane",
            smiles="CCCCCC",
            role="reactant",
            amount="1 milliliters",
        )
    )
    reaction.inputs["dummy_input"].components.add().CopyFrom(
        message_helpers.build_compound(
            name="THF",
            smiles="C1OCCC1",
            role="solvent",
            amount="40 liters",
        )
    )
    reaction.inputs["dummy_input2"].components.add().CopyFrom(
        message_helpers.build_compound(
            name="Pd",
            smiles="[Pd]",
            role="catalyst",
            amount="catalytic",
        )
    )
    reaction.conditions.pressure.atmosphere.type = reaction_pb2.PressureConditions.Atmosphere.OXYGEN
    reaction.conditions.stirring.rate.rpm = 100
    reaction.conditions.temperature.control.type = reaction_pb2.TemperatureConditions.TemperatureControl.OIL_BATH
    reaction.conditions.temperature.setpoint.CopyFrom(
        reaction_pb2.Temperature(value=100, units=reaction_pb2.Temperature.CELSIUS)
    )
    outcome = reaction.outcomes.add()
    outcome.reaction_time.CopyFrom(resolver.resolve("40 minutes"))
    outcome.products.add().identifiers.extend(
        message_helpers.build_compound(name="hexanone", smiles="CCCCC(=O)C").identifiers
    )
    yield reaction
Пример #2
0
 def setUp(self):
     super().setUp()
     self.test_subdirectory = tempfile.mkdtemp(dir=flags.FLAGS.test_tmpdir)
     self._resolver = units.UnitResolver()
     reaction = reaction_pb2.Reaction()
     reaction.setup.is_automated = True
     reaction.inputs['dummy_input'].components.add().CopyFrom(
         message_helpers.build_compound(
             name='n-hexane',
             smiles='CCCCCC',
             role='reactant',
             amount='1 milliliters',
         ))
     reaction.inputs['dummy_input'].components.add().CopyFrom(
         message_helpers.build_compound(
             name='THF',
             smiles='C1OCCC1',
             role='solvent',
             amount='40 liters',
         ))
     reaction.conditions.pressure.atmosphere.type = (
         reaction_pb2.PressureConditions.Atmosphere.OXYGEN)
     reaction.conditions.stirring.rate.rpm = 100
     reaction.conditions.temperature.control.type = (
         reaction_pb2.TemperatureConditions.TemperatureControl.OIL_BATH)
     reaction.conditions.temperature.setpoint.CopyFrom(
         reaction_pb2.Temperature(value=100,
                                  units=reaction_pb2.Temperature.CELSIUS))
     outcome = reaction.outcomes.add()
     outcome.reaction_time.CopyFrom(self._resolver.resolve('40 minutes'))
     outcome.products.add().identifiers.extend(
         message_helpers.build_compound(
             name='hexanone',
             smiles='CCCCC(=O)C',
         ).identifiers)
     reaction.reaction_id = 'dummy_reaction_id'
     self._reaction = reaction
     self._input = os.path.join(self.test_subdirectory, 'reaction.pbtxt')
     message_helpers.write_message(self._reaction, self._input)
Пример #3
0
    def setUp(self):
        super().setUp()
        self._resolver = units.UnitResolver()

        reaction = reaction_pb2.Reaction()
        reaction.setup.is_automated = reaction_pb2.Boolean.TRUE
        reaction.inputs['dummy_input'].components.add().CopyFrom(
            message_helpers.build_compound(
                name='n-hexane',
                smiles='CCCCCC',
                role='reactant',
                amount='1 milliliters',
            ))
        reaction.inputs['dummy_input'].components.add().CopyFrom(
            message_helpers.build_compound(
                name='C1OCCC1',
                smiles='THF',
                role='solvent',
                amount='40 liters',
            ))
        reaction.conditions.pressure.atmosphere.type = (
            reaction_pb2.PressureConditions.Atmosphere.OXYGEN)
        reaction.conditions.stirring.rate.rpm = 100
        reaction.conditions.temperature.control.type = (
            reaction_pb2.TemperatureConditions.TemperatureControl.OIL_BATH)
        reaction.conditions.temperature.setpoint.CopyFrom(
            reaction_pb2.Temperature(value=100,
                                     units=reaction_pb2.Temperature.CELSIUS))
        outcome = reaction.outcomes.add()
        outcome.reaction_time.CopyFrom(self._resolver.resolve('40 minutes'))
        outcome.products.add().compound.CopyFrom(
            message_helpers.build_compound(
                name='hexanone',
                smiles='CCCCC(=O)C',
                role='product',
            ))
        reaction.reaction_id = 'dummy_reaction_id'
        self._reaction = reaction
Пример #4
0
 def setUp(self):
     super().setUp()
     self._resolver = units.UnitResolver()
Пример #5
0
def build_compound(smiles=None,
                   name=None,
                   amount=None,
                   role=None,
                   is_limiting=None,
                   prep=None,
                   prep_details=None,
                   vendor=None):
    """Builds a Compound message with the most common fields.

    Args:
        smiles: Text compound SMILES.
        name: Text compound name.
        amount: Text amount string, e.g. '1.25 g'.
        role: Text reaction role. Must match a value in ReactionRoleType.
        is_limiting: Boolean whether this compound is limiting for the reaction.
        prep: Text compound preparation type. Must match a value in
            PreparationType.
        prep_details: Text compound preparation details. If provided, `prep` is
            required.
        vendor: Text compound vendor/supplier.

    Returns:
        Compound message.

    Raises:
        KeyError: if `role` or `prep` does not match a supported enum value.
        TypeError: if `amount` units are not supported.
        ValueError: if `prep_details` is provided and `prep` is None.
    """
    compound = reaction_pb2.Compound()
    if smiles:
        compound.identifiers.add(value=smiles, type='SMILES')
    if name:
        compound.identifiers.add(value=name, type='NAME')
    if amount:
        resolver = units.UnitResolver()
        amount_pb = resolver.resolve(amount)
        if isinstance(amount_pb, reaction_pb2.Mass):
            compound.amount.mass.CopyFrom(amount_pb)
        elif isinstance(amount_pb, reaction_pb2.Moles):
            compound.amount.moles.CopyFrom(amount_pb)
        elif isinstance(amount_pb, reaction_pb2.Volume):
            compound.amount.volume.CopyFrom(amount_pb)
        else:
            raise TypeError(f'unsupported units for amount: {amount_pb}')
    if role:
        field = reaction_pb2.Compound.DESCRIPTOR.fields_by_name[
            'reaction_role']
        values_dict = field.enum_type.values_by_name
        try:
            compound.reaction_role = values_dict[role.upper()].number
        except KeyError as error:
            raise KeyError(
                f'{role} is not a supported type: {values_dict.keys()}'
            ) from error
    if is_limiting is not None:
        if not (is_limiting is True or is_limiting is False):
            raise TypeError(
                f'is_limiting must be a boolean value: {is_limiting}')
        compound.is_limiting = is_limiting
    if prep:
        field = reaction_pb2.CompoundPreparation.DESCRIPTOR.fields_by_name[
            'type']
        values_dict = field.enum_type.values_by_name
        try:
            compound.preparations.add().type = values_dict[prep.upper()].number
        except KeyError as error:
            raise KeyError(
                f'{prep} is not a supported type: {values_dict.keys()}'
            ) from error
        if (compound.preparations[0].type
                == reaction_pb2.CompoundPreparation.CUSTOM
                and not prep_details):
            raise ValueError(
                'prep_details must be provided when CUSTOM prep is used')
    if prep_details:
        if not prep:
            raise ValueError('prep must be provided when prep_details is used')
        compound.preparations[0].details = prep_details
    if vendor:
        compound.source.vendor = vendor
    return compound
Пример #6
0
def set_solute_moles(solute, solvents, concentration, overwrite=False):
    """Helps define components for stock solution inputs with a single solute
    and a one or more solvent compounds.

    Args:
        solute: Compound with identifiers, roles, etc.; this argument is
            modified in place to define an amount in moles.
        solvents: list of Compounds each with defined volume.
        concentration: string defining solute concentration.
        overwrite: whether to overwrite an existing solute amount if defined.
            Defaults to False

    Raises:
        ValueError: if any solvent does not have a defined volume.
        ValueError: if the solute has an existing amount field and overwrite
            is set to False.

    Returns:
        List of Compounds to assign to a repeated components field.
    """
    # Check solute definition
    if solute.amount.WhichOneof('kind') and not overwrite:
        raise ValueError('solute has defined amount and overwrite is False')

    # Get total solvent volume in liters.
    volume_liter = 0
    for solvent in solvents:
        amount = solvent.amount
        if not amount.HasField('volume') or not amount.volume.value:
            raise ValueError('solvent must have defined volume')
        if amount.volume.units == amount.volume.LITER:
            volume_liter += amount.volume.value
        elif amount.volume.units == amount.volume.MILLILITER:
            volume_liter += amount.volume.value * 1e-3
        elif amount.volume.units == amount.volume.MICROLITER:
            volume_liter += amount.volume.value * 1e-6
        elif amount.volume.units == amount.volume.NANOLITER:
            volume_liter += amount.volume.value * 1e-9
        else:
            raise ValueError(
                'solvent units not recognized by set_solute_moles')
    # Get solute concentration in molar.
    resolver = units.UnitResolver(
        unit_synonyms=units.CONCENTRATION_UNIT_SYNONYMS, forbidden_units={})
    concentration_pb = resolver.resolve(concentration)
    if concentration_pb.units == concentration_pb.MOLAR:
        concentration_molar = concentration_pb.value
    elif concentration_pb.units == concentration_pb.MILLIMOLAR:
        concentration_molar = concentration_pb.value * 1e-3
    elif concentration_pb.units == concentration_pb.MICROMOLAR:
        concentration_molar = concentration_pb.value * 1e-6
    else:
        raise ValueError(f'unsupported units: {concentration_pb.units}')
    # Assign moles amount and return.
    moles = volume_liter * concentration_molar
    if moles < 1e-6:
        value = moles * 1e9
        unit = reaction_pb2.Moles.NANOMOLE
    elif moles < 1e-3:
        value = moles * 1e6
        unit = reaction_pb2.Moles.MICROMOLE
    elif moles < 1:
        value = moles * 1e3
        unit = reaction_pb2.Moles.MILLIMOLE
    else:
        value = moles
        unit = reaction_pb2.Moles.MOLE
    solute.amount.moles.value = value
    solute.amount.moles.units = unit
    return [solute] + solvents