예제 #1
0
 def test_is_limiting(self):
     self.assertTrue(
         message_helpers.build_compound(is_limiting=True).is_limiting)
     self.assertFalse(
         message_helpers.build_compound(is_limiting=False).is_limiting)
     self.assertFalse(
         message_helpers.build_compound().HasField('is_limiting'))
예제 #2
0
 def test_set_solute_moles(self):
     solute = message_helpers.build_compound(name='Solute')
     solvent2 = message_helpers.build_compound(name='Solvent',
                                               amount='100 mL')
     message_helpers.set_solute_moles(solute, [solvent2], '1 molar')
     self.assertEqual(solute.amount.moles,
                      reaction_pb2.Moles(units='MILLIMOLE', value=100))
     solvent3 = message_helpers.build_compound(name='Solvent',
                                               amount='75 uL')
     message_helpers.set_solute_moles(solute, [solvent3],
                                      '3 mM',
                                      overwrite=True)
     self.assertEqual(solute.amount.moles,
                      reaction_pb2.Moles(units='NANOMOLE', value=225))
     solvent4 = message_helpers.build_compound(name='Solvent',
                                               amount='0.2 uL')
     message_helpers.set_solute_moles(solute, [solvent4],
                                      '30 mM',
                                      overwrite=True)
     self.assertEqual(solute.amount.moles,
                      reaction_pb2.Moles(units='NANOMOLE', value=6))
     solvent5 = message_helpers.build_compound(name='Solvent',
                                               amount='0.8 uL')
     message_helpers.set_solute_moles(solute, [solvent4, solvent5],
                                      '30 mM',
                                      overwrite=True)
     self.assertEqual(solute.amount.moles,
                      reaction_pb2.Moles(units='NANOMOLE', value=30))
예제 #3
0
    def test_set_solute_moles_should_fail(self):
        solute = message_helpers.build_compound(name='Solute')
        solvent = message_helpers.build_compound(name='Solvent')
        with self.assertRaisesRegex(ValueError, 'defined volume'):
            message_helpers.set_solute_moles(solute, [solvent], '10 mM')

        solute = message_helpers.build_compound(name='Solute', amount='1 mol')
        solvent = message_helpers.build_compound(name='Solvent', amount='1 L')
        with self.assertRaisesRegex(ValueError, 'overwrite'):
            message_helpers.set_solute_moles(solute, [solvent], '10 mM')
예제 #4
0
 def test_is_limiting(self):
     self.assertTrue(
         message_helpers.unconvert_boolean(
             message_helpers.build_compound(is_limiting=True).is_limiting))
     self.assertFalse(
         message_helpers.unconvert_boolean(
             message_helpers.build_compound(is_limiting=False).is_limiting))
     self.assertEqual(
         message_helpers.unconvert_boolean(
             message_helpers.build_compound().is_limiting), None)
예제 #5
0
 def test_smiles_and_name(self):
     compound = message_helpers.build_compound(smiles='c1ccccc1',
                                               name='benzene')
     expected = reaction_pb2.Compound(identifiers=[
         reaction_pb2.CompoundIdentifier(value='c1ccccc1', type='SMILES'),
         reaction_pb2.CompoundIdentifier(value='benzene', type='NAME')
     ])
     self.assertEqual(compound, expected)
예제 #6
0
def resolve_input(input_string):
    """Resolve a text-based description of an input in one of the following
    formats:
        (1) [AMOUNT] of [NAME]
        (2) [AMOUNT] of [CONCENTRATION] [SOLUTE] in [SOLVENT]

    Args:
        input_string: String describing the input.

    Returns:
        ReactionInput message.

    Raises:
        ValueError: if the string cannot be parsed properly.
    """
    reaction_input = reaction_pb2.ReactionInput()
    if ' of ' not in input_string:
        raise ValueError('String does not match template!')
    amount_string, description = input_string.split(' of ')
    if ' in ' not in description:
        component_name = description
        component = reaction_input.components.add()
        component.CopyFrom(
            message_helpers.build_compound(name=component_name.strip(),
                                           amount=amount_string))
        resolve_names(reaction_input)
        return reaction_input
    pattern = re.compile(r'(\d+.?\d*)\s?(\w+)\s(.+)\sin\s(.+)')
    match = pattern.fullmatch(description.strip())
    if not match:
        raise ValueError('String did not match template!')
    conc_value, conc_units, solute_name, solvent_name = match.groups()
    solute = reaction_input.components.add()
    solvent = reaction_input.components.add()
    solute.CopyFrom(message_helpers.build_compound(name=solute_name.strip()))
    solvent.CopyFrom(
        message_helpers.build_compound(name=solvent_name.strip(),
                                       amount=amount_string))
    if solvent.amount.WhichOneof('kind') != 'volume':
        raise ValueError('Total amount of solution must be a volume!')
    solvent.amount.volume_includes_solutes = True
    message_helpers.set_solute_moles(solute, [solvent],
                                     f'{conc_value} {conc_units}')
    resolve_names(reaction_input)
    return reaction_input
예제 #7
0
 def test_get_compound_mol(self):
     mol = Chem.MolFromSmiles('c1ccccc1')
     compound = message_helpers.build_compound(smiles='c1ccccc1',
                                               name='benzene')
     identifier = compound.identifiers.add()
     identifier.type = identifier.RDKIT_BINARY
     identifier.bytes_value = mol.ToBinary()
     self.assertEqual(
         Chem.MolToSmiles(mol),
         Chem.MolToSmiles(message_helpers.get_compound_mol(compound)))
예제 #8
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
예제 #9
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)
예제 #10
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
예제 #11
0
 def test_bad_role(self):
     with self.assertRaisesRegex(KeyError, 'not a supported type'):
         message_helpers.build_compound(role='flavorant')
예제 #12
0
 def test_get_compound_smiles(self):
     compound = message_helpers.build_compound(smiles='c1ccccc1',
                                               name='benzene')
     self.assertEqual(message_helpers.get_compound_smiles(compound),
                      'c1ccccc1')
예제 #13
0
 def test_vendor(self):
     self.assertEqual(
         message_helpers.build_compound(vendor='Sally').source.vendor,
         'Sally')
예제 #14
0
 def test_custom_prep_without_details(self):
     with self.assertRaisesRegex(ValueError,
                                 'prep_details must be provided'):
         message_helpers.build_compound(prep='custom')
예제 #15
0
 def test_prep_details_without_prep(self):
     with self.assertRaisesRegex(ValueError, 'prep must be provided'):
         message_helpers.build_compound(prep_details='rinsed gently')
예제 #16
0
 def test_bad_prep(self):
     with self.assertRaisesRegex(KeyError, 'not a supported type'):
         message_helpers.build_compound(prep='shaken')
예제 #17
0
 def test_prep(self, prep, details, expected):
     compound = message_helpers.build_compound(prep=prep,
                                               prep_details=details)
     self.assertEqual(compound.preparations[0], expected)
예제 #18
0
 def test_amount(self, amount, expected):
     compound = message_helpers.build_compound(amount=amount)
     self.assertEqual(
         getattr(compound.amount, compound.amount.WhichOneof('kind')),
         expected)
예제 #19
0
 def test_role(self):
     compound = message_helpers.build_compound(role='solvent')
     self.assertEqual(compound.reaction_role,
                      reaction_pb2.ReactionRole.SOLVENT)
예제 #20
0
 def test_bad_amount(self, amount):
     with self.assertRaises((KeyError, ValueError)):
         message_helpers.build_compound(amount=amount)