def test_to_list(self):
     """Test basic ParameterList.to_list() function, ensuring units are preserved"""
     from simtk import unit
     p1 = BondHandler.BondType(smirks='[*:1]-[*:2]',
                               length=1.01 * unit.angstrom,
                               k=5 * unit.kilocalorie_per_mole /
                               unit.angstrom**2)
     p2 = BondHandler.BondType(smirks='[*:1]=[*:2]',
                               length=1.02 * unit.angstrom,
                               k=6 * unit.kilocalorie_per_mole /
                               unit.angstrom**2)
     p3 = BondHandler.BondType(smirks='[*:1]#[*:3]',
                               length=1.03 * unit.angstrom,
                               k=7 * unit.kilocalorie_per_mole /
                               unit.angstrom**2)
     parameter_list = ParameterList([p1, p2, p3])
     ser_param_list = parameter_list.to_list()
     assert len(ser_param_list) == 3
     assert ser_param_list[0]['length'] == 1.01 * unit.angstrom
    def test_read_write_optional_parameter_attribute(self):
        """
        Test ParameterTypes' ability to store and write out optional attributes passed to __init__()
        """
        from simtk import unit

        p1 = BondHandler.BondType(smirks='[*:1]-[*:2]',
                                  length=1.02 * unit.angstrom,
                                  k=5 * unit.kilocalorie_per_mole /
                                  unit.angstrom**2,
                                  id='b1')
        param_dict = p1.to_dict()
        assert ('id', 'b1') in param_dict.items()
 def test_round_trip(self):
     """Test basic ParameterList.to_list() function and constructor"""
     from simtk import unit
     p1 = BondHandler.BondType(smirks='[*:1]-[*:2]',
                               length=1.01 * unit.angstrom,
                               k=5 * unit.kilocalorie_per_mole /
                               unit.angstrom**2)
     p2 = BondHandler.BondType(smirks='[*:1]=[*:2]',
                               length=1.02 * unit.angstrom,
                               k=6 * unit.kilocalorie_per_mole /
                               unit.angstrom**2)
     p3 = BondHandler.BondType(smirks='[*:1]#[*:3]',
                               length=1.03 * unit.angstrom,
                               k=7 * unit.kilocalorie_per_mole /
                               unit.angstrom**2)
     parameter_list = ParameterList([p1, p2, p3])
     param_dict_list = parameter_list.to_list()
     parameter_list_2 = ParameterList()
     for param_dict in param_dict_list:
         new_parameter = BondHandler.BondType(**param_dict)
         parameter_list_2.append(new_parameter)
     assert parameter_list.to_list() == parameter_list_2.to_list()
    def test_error_cosmetic_parameter_attribute(self):
        """
        Test that ParameterTypes raise an error on receiving unexpected attributes passed to __init__()
        """
        from simtk import unit

        with pytest.raises(SMIRNOFFSpecError, match="Unexpected kwarg (pilot: alice)*") as context:
            p1 = BondHandler.BondType(smirks='[*:1]-[*:2]',
                                      length=1.02*unit.angstrom,
                                      k=5 * unit.kilocalorie_per_mole / unit.angstrom ** 2,
                                      pilot='alice',
                                      allow_cosmetic_attributes=False
                                      )
    def test_read_but_dont_write_cosmetic_parameter_attribute(self):
        """
        Test ParameterTypes' ability to ignore cosmetic attributes passed to __init__() if instructed
        """
        from simtk import unit

        p1 = BondHandler.BondType(smirks='[*:1]-[*:2]',
                                  length=1.02 * unit.angstrom,
                                  k=5 * unit.kilocalorie_per_mole /
                                  unit.angstrom**2,
                                  pilot='alice',
                                  allow_cosmetic_attributes=True)
        param_dict = p1.to_dict(discard_cosmetic_attributes=True)
        assert ('pilot', 'alice') not in param_dict.items()
 def test_bondtype_to_dict_custom_output_units(self):
     """
     Test BondType to_dict with custom output units.
     """
     from simtk import unit
     p1 = BondHandler.BondType(smirks='[*:1]-[*:2]',
                               length=1.02 * unit.angstrom,
                               k=5 * unit.kilocalorie_per_mole /
                               unit.angstrom**2)
     param_dict = p1.to_dict()
     param_dict_unitless, attached_units = detach_units(
         param_dict, output_units={'length_unit': unit.nanometer})
     assert attached_units['length_unit'] == unit.nanometer
     assert abs(param_dict_unitless['length'] - 0.102) < 1e-10
 def test_bondtype_to_dict_invalid_output_units(self):
     """
     Test ParameterType to_dict with invalid output units.
     """
     from simtk import unit
     p1 = BondHandler.BondType(smirks='[*:1]-[*:2]',
                               length=1.02*unit.angstrom,
                               k=5 * unit.kilocalorie_per_mole / unit.angstrom ** 2
                               )
     param_dict = p1.to_dict()
     with pytest.raises(ValueError,
                        match='Requested output unit calorie is not compatible with quantity unit angstrom .'
                        ) as context:
         param_dict_unitless, attached_units = detach_units(param_dict, output_units = {'length_unit':
                                                                                            unit.calorie})
 def test_to_dict_maintain_units(self):
     """Test ParameterHandler.to_dict() function when parameters were provided in different units
     """
     from simtk import unit
     bh = BondHandler(skip_version_check=True)
     bh.add_parameter({'smirks': '[*:1]-[*:2]',
                       'length': 1*unit.angstrom,
                       'k': 10*unit.kilocalorie_per_mole/unit.angstrom**2})
     bh.add_parameter({'smirks': '[*:1]=[*:2]',
                       'length': 0.2*unit.nanometer,
                       'k': 0.4*unit.kilojoule_per_mole/unit.nanometer**2})
     bh_dict = bh.to_dict()
     assert bh_dict['Bond'][0]['length'] == unit.Quantity(1., unit.angstrom)
     assert bh_dict['Bond'][0]['length'].unit == unit.angstrom
     assert bh_dict['Bond'][1]['length'] == unit.Quantity(0.2, unit.nanometer)
     assert bh_dict['Bond'][1]['length'].unit == unit.nanometer
 def test_different_units_to_dict(self):
     """Test ParameterHandler.to_dict() function when some parameters are in
     different units (proper behavior is to convert all quantities to the last-
     read unit)
     """
     from simtk import unit
     bh = BondHandler(skip_version_check=True)
     bh.add_parameter({'smirks': '[*:1]-[*:2]',
                       'length': 1*unit.angstrom,
                       'k': 10*unit.kilocalorie_per_mole/unit.angstrom**2})
     bh.add_parameter({'smirks': '[*:1]=[*:2]',
                       'length': 0.2*unit.nanometer,
                       'k': 0.4*unit.kilojoule_per_mole/unit.nanometer**2})
     bh_dict = bh.to_dict()
     assert bh_dict['Bond'][0]['length'] == unit.Quantity(value=1, unit=unit.angstrom)
     assert bh_dict['Bond'][1]['length'] == unit.Quantity(value=2, unit=unit.angstrom)
    def test_bondtype_to_dict(self):
        """
        Test BondType to_dict.
        """
        from simtk import unit

        p1 = BondHandler.BondType(smirks='[*:1]-[*:2]',
                                  length=1.02 * unit.angstrom,
                                  k=5 * unit.kilocalorie_per_mole / unit.angstrom ** 2
                                  )
        param_dict = p1.to_dict()
        param_dict_unitless, attached_units = detach_units(param_dict)
        assert param_dict_unitless == {'smirks': '[*:1]-[*:2]',
                                       'length': 1.02,
                                       'k': 5,}
        assert attached_units == {'length_unit': unit.angstrom,
                                  'k_unit': (unit.angstrom ** -2) * (unit.mole ** -1) * (unit.kilocalorie ** 1)
                                  }
    def test_add_delete_cosmetic_attrib(self):
        """
        Test adding and deleting cosmetic attributes for already-initialized ParameterType objects
        """
        from simtk import unit

        p1 = BondHandler.BondType(smirks='[*:1]-[*:2]',
                                  length=1.02*unit.angstrom,
                                  k=5 * unit.kilocalorie_per_mole / unit.angstrom ** 2,
                                  )
        # Ensure the cosmetic attribute is present by default during output
        p1.add_cosmetic_attribute('pilot', 'alice')
        param_dict = p1.to_dict()
        assert ('pilot', 'alice') in param_dict.items()

        # Ensure the cosmetic attribute isn't present if we request that it be discarded
        param_dict = p1.to_dict(discard_cosmetic_attributes=True)
        assert ('pilot', 'alice') not in param_dict.items()

        # Manually delete the cosmetic attribute and ensure it doesn't get written out
        p1.delete_cosmetic_attribute('pilot')
        param_dict = p1.to_dict()
        assert ('pilot', 'alice') not in param_dict.items()
    def test_add_delete_cosmetic_attributes(self):
        """Test ParameterHandler.to_dict() function when some parameters are in
        different units (proper behavior is to convert all quantities to the last-
        read unit)
        """
        from simtk import unit
        bh = BondHandler(skip_version_check=True)
        bh.add_parameter({
            'smirks': '[*:1]-[*:2]',
            'length': 1 * unit.angstrom,
            'k': 10 * unit.kilocalorie_per_mole / unit.angstrom**2
        })
        bh.add_parameter({
            'smirks': '[*:1]=[*:2]',
            'length': 0.2 * unit.nanometer,
            'k': 0.4 * unit.kilojoule_per_mole / unit.nanometer**2
        })

        assert not (bh.attribute_is_cosmetic('pilot'))

        # Ensure the cosmetic attribute is present by default during output
        bh.add_cosmetic_attribute('pilot', 'alice')
        param_dict = bh.to_dict()
        assert ('pilot', 'alice') in param_dict.items()
        assert bh.attribute_is_cosmetic('pilot')

        # Ensure the cosmetic attribute isn't present if we request that it be discarded
        param_dict = bh.to_dict(discard_cosmetic_attributes=True)
        assert 'pilot' not in param_dict

        # Manually delete the cosmetic attribute and ensure it doesn't get written out
        bh.delete_cosmetic_attribute('pilot')
        param_dict = bh.to_dict()
        assert 'pilot' not in param_dict
        assert not (bh.attribute_is_cosmetic('pilot'))
    def test_get_parameter(self):
        """Test that ParameterHandler.get_parameter can lookup function
        """
        from simtk import unit
        bh = BondHandler(skip_version_check=True, allow_cosmetic_attributes=True)

        bh.add_parameter({'smirks': '[*:1]-[*:2]',
                          'length': 1*unit.angstrom,
                          'k': 10*unit.kilocalorie_per_mole/unit.angstrom**2,
                          'id': 'b0'})
        bh.parameters[0].add_cosmetic_attribute('foo', 'bar')

        # Check base behavior
        params = bh.get_parameter({'smirks': '[*:1]-[*:2]'})

        assert params[0].length == unit.Quantity(1.0, unit.angstrom)
        assert params[0].k == unit.Quantity(10.0, unit.kilocalorie_per_mole/unit.angstrom**2)

        # Ensure a query with no matches returns an empty list
        assert not bh.get_parameter({'smirks': 'xyz'})

        # Ensure searching for a nonexistent attr does not raise an exception
        assert not bh.get_parameter({'bAdAttR': '0'})

        # Check for optional and cosmetic attrs
        optional_params = bh.get_parameter({'id': 'b0'})
        cosmetic_params = bh.get_parameter({'foo': 'bar'})

        assert optional_params[0].id == 'b0'
        assert cosmetic_params[0]._foo == 'bar'

        # Ensure selection behaves a "OR" not "AND"
        bh.add_parameter({'smirks': '[#1:1]-[#6:2]',
                          'length': 1*unit.angstrom,
                          'k': 10*unit.kilocalorie_per_mole/unit.angstrom**2,
                          'id': 'b1'})

        params = bh.get_parameter({'id': 'b0', 'smirks': '[#1:1]-[#6:2]'})

        assert 'b0' in [param.id for param in params]
        assert '[*:1]-[*:2]' in [param.smirks for param in params]

        # Ensure selection does not return duplicates if multiple matches
        params = bh.get_parameter({'id': 'b1', 'smirks': '[#1:1]-[#6:2]'})

        assert len(params) == 1