def _new_property(self, key, value):
        """ Create a new list of properties for each frame. To facilitate analysis, will try
        to create this list as one of the following classes (in order of preference):
          1) resizeable numpy array
          2) resizeable MdtQuantity array
          3) list

        The list of properties will be backfilled with ``None`` if this property wasn't already
        present
        """
        assert key not in self.properties

        if self.num_frames != 0:
            proplist = [None] * self.num_frames
            proplist.append(value)
        else:
            try:
                proplist = self.unit_system.convert(u.array([value]))
            except TypeError:
                proplist = [value]
            else:
                proplist.make_resizable()
                if proplist.dimensionless:
                    proplist = proplist._magnitude

        self.properties[key] = proplist
    def rmsd(self, atoms=None, reference=None):
        r""" Calculate root-mean-square displacement for each frame in the trajectory.

        The RMSD between times :math:`t` and :math:`t0` is given by

        :math:`\text{RMSD}(t;t_0) =\sqrt{\sum_{i \in \text{atoms}} \left( \mathbf{R}_i(t) -
        \mathbf{R}_i(t_0) \right)^2}`,

        where :math:`\mathbf{R}_i(t)` is the position of atom *i* at time *t*.


        Args:
            atoms (list[mdt.Atom]): list of atoms to calculate the RMSD for (all atoms in the
                ``Molecule``)
            reference (u.Vector[length]): Reference positions for RMSD. (default:
                ``traj.frames[0].positions``)

        Returns:
            u.Vector[length]: list of RMSD displacements for each frame in the trajectory

        """
        if reference is None: refpos = self.frames[0].positions
        else: refpos = reference.positions

        atoms = mdt.utils.if_not_none(atoms, self.mol.atoms)
        indices = np.array([atom.index for atom in atoms])

        rmsds = []
        for f in self.frames:
            diff = (refpos[indices] - f.positions[indices])
            rmsds.append(np.sqrt((diff * diff).sum() / len(atoms)))
        return u.array(rmsds).defunits()
    def rmsd(self, atoms=None, reference=None):
        r""" Calculate root-mean-square displacement for each frame in the trajectory.

        The RMSD between times :math:`t` and :math:`t0` is given by

        :math:`\text{RMSD}(t;t_0) =\sqrt{\sum_{i \in \text{atoms}} \left( \mathbf{R}_i(t) -
        \mathbf{R}_i(t_0) \right)^2}`,

        where :math:`\mathbf{R}_i(t)` is the position of atom *i* at time *t*.


        Args:
            atoms (list[mdt.Atom]): list of atoms to calculate the RMSD for (all atoms in the
                ``Molecule``)
            reference (u.Vector[length]): Reference positions for RMSD. (default:
                ``traj.frames[0].positions``)

        Returns:
            u.Vector[length]: list of RMSD displacements for each frame in the trajectory

        """
        if reference is None: refpos = self.frames[0].positions
        else: refpos = reference.positions

        atoms = mdt.utils.if_not_none(atoms, self.mol.atoms)
        indices = np.array([atom.index for atom in atoms])

        rmsds = []
        for f in self.frames:
            diff = (refpos[indices] - f.positions[indices])
            rmsds.append(np.sqrt((diff*diff).sum()/len(atoms)))
        return u.array(rmsds).defunits()
def test_bond_alignment_on_axis(benzene):
    mol = benzene.copy()
    directions = [
        'x', 'y', 'z', [1, 2, 3.0], [0, 1, 0], [0.1, 0.1, 0.1] * u.angstrom
    ]

    for i, dir in enumerate(directions):
        bond = mdt.Bond(*random.sample(mol.atoms, 2))
        center = (i % 2) == 0.0
        bond.align(dir, centered=center)

        if center:
            np.testing.assert_allclose(bond.midpoint, np.zeros(3), atol=1.e-12)
            np.testing.assert_allclose(bond.a1.position.defunits_value(),
                                       -bond.a2.position.defunits_value(),
                                       atol=1e-10)
        if isinstance(dir, str):
            if dir == 'x':
                d = np.array([1.0, 0, 0])
            elif dir == 'y':
                d = np.array([0.0, 1.0, 0.0])
            elif dir == 'z':
                d = np.array([0.0, 0.0, 1.0])
            else:
                raise WtfError()
        else:
            d = normalized(u.array(dir))

        newvec = (bond.a2.position - bond.a1.position).normalized()
        assert abs(1.0 - d.dot(newvec)) < 1e-10
示例#5
0
 def calculate(self, requests):
     dvec = self.mol.atoms[1].position - self.mol.atoms[0].position
     dist = np.sqrt(dvec.dot(dvec))
     pe = 0.5 * self.k * (dist - self.d0)**2
     f = self.k * dvec * (dist - self.d0) / dist
     forcearray = u.array([f, -f])
     return {'potential_energy': pe, 'forces': forcearray}
    def _new_property(self, key, value):
        """ Create a new list of properties for each frame. To facilitate analysis, will try
        to create this list as one of the following classes (in order of preference):
          1) resizeable numpy array
          2) resizeable MdtQuantity array
          3) list

        The list of properties will be backfilled with ``None`` if this property wasn't already
        present
        """
        assert key not in self.properties

        if self.num_frames != 0:
            proplist = [None] * self.num_frames
            proplist.append(value)
        else:
            try:
                proplist = self.unit_system.convert(u.array([value]))
            except TypeError:
                proplist = [value]
            else:
                proplist.make_resizable()
                if proplist.dimensionless:
                    proplist = proplist._magnitude

        self.properties[key] = proplist
示例#7
0
def test_container_properties(fixturename, request):
    obj = request.getfixturevalue(fixturename)
    assert obj.mass == sum([atom.mass for atom in obj.atoms])
    np.testing.assert_array_equal(
        obj.positions.defunits(),
        u.array([atom.position for atom in obj.atoms]).defunits())
    assert obj.num_atoms == len(obj.atoms)
def test_bond_alignment_on_axis(benzene):
    mol = benzene.copy()
    directions = ['x', 'y', 'z',
                  [1,2,3.0],
                  [0,1,0],
                  [0.1, 0.1, 0.1] * u.angstrom]

    for i, dir in enumerate(directions):
        bond = mdt.Bond(*random.sample(mol.atoms, 2))
        center = (i % 2) == 0.0
        bond.align(dir, centered=center)

        if center:
            np.testing.assert_allclose(bond.midpoint, np.zeros(3),
                                       atol=1.e-12)
            np.testing.assert_allclose(bond.a1.position.defunits_value(),
                                       -bond.a2.position.defunits_value(),
                                       atol=1e-10)
        if isinstance(dir, str):
            if dir == 'x':
                d = np.array([1.0, 0, 0])
            elif dir == 'y':
                d = np.array([0.0, 1.0, 0.0])
            elif dir == 'z':
                d = np.array([0.0, 0.0, 1.0])
            else:
                raise WtfError()
        else:
            d = normalized(u.array(dir))

        newvec = (bond.a2.position - bond.a1.position).normalized()
        assert abs(1.0 - d.dot(newvec)) < 1e-10
示例#9
0
 def calculate(self, requests):
     dvec = self.mol.atoms[1].position - self.mol.atoms[0].position
     dist = np.sqrt(dvec.dot(dvec))
     pe = 0.5 * self.params.k * (dist - self.params.d0)**2
     f = self.params.k * dvec * (dist - self.params.d0) / dist
     forcearray = u.array([f, -f])
     return {'potential_energy': pe,
             'forces': forcearray}
def test_default_unit_conversions():
    my_list = [1.0 * units.angstrom, 1.0 * units.nm, 1.0 * units.a0]
    my_array = units.array(my_list).defunits()
    assert my_array.get_units() == units.default.convert(my_array).get_units()
    result = my_array.value_in(units.nm)
    np.testing.assert_almost_equal(result[0], 0.1, 9)
    np.testing.assert_almost_equal(result[1], 1.0, 9)
    np.testing.assert_almost_equal(result[2], 0.05291772, 7)
def test_dimensionless_array_from_mixed_data():
    data = [
        np.arange(3), [1.0 * u.dimensionless, 1.0 * u.nm / u.angstrom, 3.0],
        [1, 1, 1] * u.ureg.kg / u.ureg.g
    ]
    arr = u.array(data)
    np.testing.assert_allclose(
        arr,
        np.array([[0, 1, 2], [1, 10, 3], [1000, 1000, 1000]], dtype='float'))
    assert isinstance(arr, np.ndarray)
示例#12
0
    def transform(self, matrix):
        """ Transform this object's coordinates using the provided 4x4 matrix

        Args:
            matrix (numpy.ndarray): transformation matrix, shape=(4,4)
        """
        # TODO: deal with units ... hard because the matrix has diff units for diff columns
        assert matrix.shape == (4, 4)
        positions = u.array(self.atoms.position)
        newpos = mathutils.apply_4x4_transform(matrix, positions)
        for atom, r in zip(self.atoms, newpos):
            atom.position = r
示例#13
0
 def __getattr__(self, item):
     """
     Returns an array of atomic properties, e.g., an array of all atomic masses
     is returned by ``AtomContainer.mass = AtomContainer.__getattr__('mass')``
     """
     if item.startswith('__'):
         raise AttributeError
     atom_attrs = [getattr(atom, item) for atom in self.atoms]
     try:
         return u.array(atom_attrs)
     except (TypeError, StopIteration):
         return atom_attrs
示例#14
0
def colormap(cats, mplmap='auto', categorical=None):
    """ Map a series of categories to hex colors, using a matplotlib colormap

    Generates both categorical and numerical colormaps.

    Args:
        cats (Iterable): list of categories or numerical values
        mplmap (str): name of matplotlib colormap object
        categorical (bool): If None
            (the default) interpret data as numerical only if it can be cast to float.
            If True, interpret this data as categorical. If False, cast the data to float.

    Returns:
        List[str]: List of hexadecimal RGB color values in the in the form ``'#000102'``
    """
    # Should automatically choose the right colormaps for:
    #  categorical data
    #  sequential data (low, high important)
    #  diverging data (low, mid, high important)
    global DEF_SEQUENTIAL
    from matplotlib import cm

    if hasattr(cm, 'inferno'):
        DEF_SEQUENTIAL = 'inferno'
    else:
        DEF_SEQUENTIAL = 'BrBG'

    # strip units
    units = None  # TODO: build a color bar with units
    if hasattr(cats[0], 'magnitude'):
        arr = u.array(cats)
        units = arr.units
        cats = arr.magnitude
        is_categorical = False
    else:
        is_categorical = not isinstance(cats[0], (float, int))

    if categorical is not None:
        is_categorical = categorical

    if is_categorical:
        values = _map_categories_to_ints(cats)
        if mplmap == 'auto':
            mplmap = DEF_CATEGORICAL
    else:
        values = np.array(list(map(float, cats)))
        if mplmap == 'auto':
            mplmap = DEF_SEQUENTIAL

    rgb = _cmap_to_rgb(mplmap, values)
    hexcolors = [webcolors.rgb_to_hex(np.array(c)) for c in rgb]
    return hexcolors
def test_dimensional_array_from_mixed_data():
    data = [
        np.arange(3) * u.angstrom,
        [1.0 * u.nm, 1.0 * u.nm**2 / u.angstrom, 3.0 * u.ureg.km],
        [1, 1, 1] * u.bohr
    ]
    arr = u.array(data)

    bohr_in_ang = (1.0 * u.bohr).value_in(u.angstrom)
    expected = u.angstrom * [[0, 1, 2], [10.0, 100.0, 3.0e13],
                             [bohr_in_ang, bohr_in_ang, bohr_in_ang]]
    np.testing.assert_allclose(arr, expected)
    assert isinstance(arr, units.MdtQuantity)
    def __getattr__(self, item):  # TODO: remove and replace all __getattr__
        if item in ('traj', 'index', 'real_atom'):
            raise AttributeError('_TrajAtom.%s not assigned (pickle issue?)' % item)

        try:  # try to get a time-dependent version
            trajslice = getattr(self.traj, item)
        except AttributeError:  # not time-dependent - look for an atomic property
            return getattr(self.real_atom, item)

        if trajslice[0]['type'] != 'atomic':
            raise ValueError('%s is not an atomic quantity' % item)
        else:
            return u.array([f[self.real_atom] for f in trajslice])
示例#17
0
def colormap(cats, mplmap='auto', categorical=None):
    """ Map a series of categories to hex colors, using a matplotlib colormap

    Generates both categorical and numerical colormaps.

    Args:
        cats (Iterable): list of categories or numerical values
        mplmap (str): name of matplotlib colormap object
        categorical (bool): if True, interpret this data as categorical. If False, interpret
            the data as numerical values (data must be convertible to float)

    Returns:
        List[str]: List of hexadecimal RGB color values in the in the form ``'#000102'``
    """
    # Should automatically choose the right colormaps for:
    #  categorical data
    #  sequential data (low, high important)
    #  diverging data (low, mid, high important)
    global DEF_SEQUENTIAL
    from matplotlib import cm

    if hasattr(cm, 'inferno'):
        DEF_SEQUENTIAL = 'inferno'
    else:
        DEF_SEQUENTIAL = 'BrBG'

    # strip units
    units = None  # TODO: build a color bar with units
    if hasattr(cats[0], 'magnitude'):
        arr = u.array(cats)
        units = arr.units
        cats = arr.magnitude
        is_categorical = False
    else:
        is_categorical = not isinstance(cats[0], float)

    if categorical is not None:
        is_categorical = categorical

    if is_categorical:
        values = _map_categories_to_ints(cats)
        if mplmap == 'auto':
            mplmap = DEF_CATEGORICAL
    else:
        values = np.array(map(float, cats))
        if mplmap == 'auto':
            mplmap = DEF_SEQUENTIAL

    rgb = _cmap_to_rgb(mplmap, values)
    hexcolors = [webcolors.rgb_to_hex(np.array(c)) for c in rgb]
    return hexcolors
def test_vectorized_gaussian_function_evaluations(objkey, request):
    g = request.getfuncargvalue(objkey)

    coords = np.zeros((5, g.ndims)) * g.center.units
    for i in xrange(5):
        coords[i] = g.center
        randoffset = 4.0 * (random.random() - 0.5) * g.exp**-0.5
        idim = random.randrange(g.ndims)
        coords[i, idim] += randoffset

    vector_results = g(coords)
    expected = u.array([g(c) for c in coords])

    _assert_almost_equal(vector_results, expected, decimal=8)
    def __getattr__(self, item):  # TODO: remove and replace all __getattr__
        if item in ('traj', 'index', 'real_atom'):
            raise AttributeError('_TrajAtom.%s not assigned (pickle issue?)' %
                                 item)

        try:  # try to get a time-dependent version
            trajslice = getattr(self.traj, item)
        except AttributeError:  # not time-dependent - look for an atomic property
            return getattr(self.real_atom, item)

        if trajslice[0]['type'] != 'atomic':
            raise ValueError('%s is not an atomic quantity' % item)
        else:
            return u.array([f[self.real_atom] for f in trajslice])
def test_vectorized_gaussian_function_evaluations(objkey, request):
    g = request.getfuncargvalue(objkey)

    coords = np.zeros((5, g.ndims)) * g.center.units
    for i in xrange(5):
        coords[i] = g.center
        randoffset = 4.0 * (random.random() - 0.5) * g.exp**-0.5
        idim = random.randrange(g.ndims)
        coords[i, idim] += randoffset

    vector_results = g(coords)
    expected = u.array([g(c) for c in coords])

    _assert_almost_equal(vector_results, expected, decimal=8)
示例#21
0
def test_pyscf_and_mdt_overlaps_are_the_same(h2_rhf_augccpvdz):
    mol = h2_rhf_augccpvdz
    basis = mol.wfn.aobasis

    calc_overlap_mat = []
    for i in range(len(basis)):
        calc_overlap_mat.append(
            [basis[i].overlap(basis[j]) for j in range(len(basis))])

    overlaps = u.array(calc_overlap_mat)
    assert isinstance(overlaps,
                      np.ndarray) or overlaps.units == u.dimensionless

    np.testing.assert_allclose(mol.wfn.aobasis.overlaps, overlaps, atol=5.0e-7)
 def kinetic_energy(self):
     convert_units = True
     energies = []
     for frame in self.frames:
         if 'momenta' in frame:
             energies.append(
                 helpers.kinetic_energy(frame.momenta, self.mol.dim_masses))
         else:
             convert_units = False
             energies.append(None)
     if convert_units:
         arr = u.array(energies)
         return u.default.convert(arr)
     else:
         return energies
 def kinetic_energy(self):
     convert_units = True
     energies = []
     for frame in self.frames:
         if 'momenta' in frame:
             energies.append(
                 helpers.kinetic_energy(frame.momenta, self.mol.dim_masses))
         else:
             convert_units = False
             energies.append(None)
     if convert_units:
         arr = u.array(energies)
         return u.default.convert(arr)
     else:
         return energies
 def kinetic_temperature(self):
     convert_units = True
     temps = []
     energies = self.kinetic_energy
     dof = self.mol.dynamic_dof
     for energy, frame in zip(energies, self.frames):
         if energy is not None:
             temps.append(helpers.kinetic_temperature(energy, dof))
         else:
             convert_units = False
             temps.append(None)
     if convert_units:
         arr = u.array(temps)
         return u.default.convert(arr)
     else:
         return temps
 def kinetic_temperature(self):
     convert_units = True
     temps = []
     energies = self.kinetic_energy
     dof = self.mol.dynamic_dof
     for energy, frame in zip(energies, self.frames):
         if energy is not None:
             temps.append(helpers.kinetic_temperature(energy, dof))
         else:
             convert_units = False
             temps.append(None)
     if convert_units:
         arr = u.array(temps)
         return u.default.convert(arr)
     else:
         return temps
def test_pyscf_and_mdt_overlaps_are_the_same(h2_rhf_augccpvdz):
    mol = h2_rhf_augccpvdz
    basis = mol.wfn.aobasis

    calc_overlap_mat = []
    for i in range(len(basis)):
        calc_overlap_mat.append(
                [basis[i].overlap(basis[j]) for j in range(len(basis))]
        )

    overlaps = u.array(calc_overlap_mat)
    assert isinstance(overlaps, np.ndarray) or overlaps.units == u.dimensionless

    np.testing.assert_allclose(mol.wfn.aobasis.overlaps,
                               overlaps,
                               atol=5.0e-7)
示例#27
0
def colormap(cats, mplmap='auto'):
    # should make it easy to choose one for:
    #  categorical data
    #  sequential (low, high important)
    #  diverging data (low, mid, high important)
    # Can deal with numerical and categorical data
    # we'll treat ints as categories for now
    global DEF_SEQUENTIAL
    from matplotlib import cm

    if hasattr(cm, 'inferno'):
        DEF_SEQUENTIAL = 'inferno'
    else:
        DEF_SEQUENTIAL = 'BrBG'

    # strip units
    units = None
    if hasattr(cats[0], 'magnitude'):
        arr = u.array(cats)
        units = arr.units
        cats = arr.magnitude

    if not isinstance(cats, np.ndarray) and not isinstance(cats[0],
                                                           float):  # treat as
        # categorical
        values = np.zeros(len(cats), dtype='float')
        to_int = collections.OrderedDict()
        for i, item in enumerate(cats):
            if item not in to_int:
                to_int[item] = len(to_int)
            values[i] = to_int[item]
        if mplmap == 'auto':
            mplmap = DEF_CATEGORICAL
    else:  # it's numerical
        values = np.array(cats, dtype='float')
        if mplmap == 'auto':
            mplmap = DEF_SEQUENTIAL

    cmap = getattr(cm, mplmap)
    mx = values.max()
    mn = values.min()
    r = (values - mn) / (mx - mn)  # rescale to [0.0,1.0]
    rgb = cmap(r)
    hexcolors = [webcolors.rgb_to_hex(np.array(r[:3]) * 256) for r in rgb]
    return hexcolors
def test_volumetric_grid_point_list(key, request):
    ranges = request.getfixturevalue(key)
    grid = mathutils.VolumetricGrid(*ranges, xpoints=3, ypoints=4, zpoints=5)
    assert (grid.xpoints, grid.ypoints, grid.zpoints) == (3,4,5)
    pl = list(grid.iter_points())
    pa = grid.allpoints()
    assert (u.array(pl) == pa).all()

    for i in range(3):
        assert pa[:,i].min() == ranges[i][0]
        assert pa[:,i].max() == ranges[i][1]

    assert grid.npoints == 3*4*5
    assert len(pl) == grid.npoints

    for idim in range(3):
        for ipoint in range(1,grid.points[idim]):
            helpers.assert_almost_equal(grid.spaces[idim][ipoint] - grid.spaces[idim][ipoint-1],
                                        grid.deltas[idim])
示例#29
0
def test_volumetric_grid_point_list(key, request):
    ranges = request.getfixturevalue(key)
    grid = mathutils.VolumetricGrid(*ranges, xpoints=3, ypoints=4, zpoints=5)
    assert (grid.xpoints, grid.ypoints, grid.zpoints) == (3, 4, 5)
    pl = list(grid.iter_points())
    pa = grid.allpoints()
    assert (u.array(pl) == pa).all()

    for i in range(3):
        assert pa[:, i].min() == ranges[i][0]
        assert pa[:, i].max() == ranges[i][1]

    assert grid.npoints == 3 * 4 * 5
    assert len(pl) == grid.npoints

    for idim in range(3):
        for ipoint in range(1, grid.points[idim]):
            helpers.assert_almost_equal(
                grid.spaces[idim][ipoint] - grid.spaces[idim][ipoint - 1],
                grid.deltas[idim])
示例#30
0
def test_pyscf_orbital_grid_works(h2_rhf_augccpvdz):
    """ Tests the basic input/output of the pyscf basis_values function

    Doesn't actually test the values directly - just that the answers are mathematically consistent
    """
    mol = h2_rhf_augccpvdz
    wfn = mol.wfn
    nbasis = len(wfn.aobasis)

    coords = u.array([
        mol.com,
        np.zeros(3) * u.angstrom, 10.0 * np.ones(3) * u.angstrom,
        np.ones(3) * u.nm
    ])

    # First - check that the shape is appropriate if called without orbital coefficients
    values_nocoeffs = basis_values(mol, wfn.aobasis, coords)
    assert values_nocoeffs.shape == (len(coords), nbasis)
    assert (values_nocoeffs[-1] == values_nocoeffs[-2]
            ).all()  # these 2 coordinates are the same

    # Second - explicitly send orbital coefficients for first 2 basis functions
    coeffs = np.zeros((2, nbasis))
    coeffs[:2, :2] = np.identity(2)
    vals_b0 = basis_values(mol, wfn.aobasis, coords, coeffs=coeffs)
    assert vals_b0.shape == (len(coords), len(coeffs))
    np.testing.assert_allclose(values_nocoeffs[:, :2], vals_b0)

    # Third - send symmetric and anti-symmetric combinations of basis functions and check answers
    plusminus = np.zeros((2, nbasis))
    plusminus[:2, :2] = 1.0 / np.sqrt(2)
    plusminus[1, 1] = -1.0 / np.sqrt(2)
    vals_plusminus = basis_values(mol, wfn.aobasis, coords, coeffs=plusminus)
    assert vals_plusminus.shape == (len(coords), len(coeffs))
    helpers.assert_almost_equal(vals_plusminus[:, 0],
                                (vals_b0[:, 0] + vals_b0[:, 1]) / np.sqrt(2))
    helpers.assert_almost_equal(vals_plusminus[:, 1],
                                (vals_b0[:, 0] - vals_b0[:, 1]) / np.sqrt(2))
    def slice_frames(self, key, missing=None):
        """ Return an array of giving the value of ``key`` at each frame.

        Args:
            key (str): name of the property, e.g., time, potential_energy, annotation, etc
            missing: value to return if a given frame does not have this property

        Returns:
            moldesign.units.Vector: vector containing the value at each frame, or the value given
                in the ``missing`` keyword) (len= `len(self)` )
        """
        has_units = True
        result = []
        for f in self.frames:
            val = f.get(key, None)
            if not issubclass(type(val), u.MdtQuantity):
                has_units = False
            result.append(val)
        if has_units:
            result = u.array([frame.get(key, None) for frame in self.frames])
            return u.default.convert(result)
        else:
            return np.array(result)
    def __getattr__(self, item):
        if item in ('traj', 'index', 'real_atom'):
            raise AttributeError('_TrajAtom.%s not assigned (pickle issue?)' %
                                 item)

        if item in self.ATOMIC_ARRAYS:
            is_array = True
            item = self.ATOMIC_ARRAYS[item]
        else:
            is_array = False

        try:  # try to get a time-dependent version
            trajslice = getattr(self.traj, item)
        except AttributeError:  # not time-dependent - look for an atomic property
            return getattr(self.real_atom, item)

        if is_array:
            return trajslice[:, self.index, :]
        else:
            if trajslice[0]['type'] != 'atomic':
                raise ValueError('%s is not an atomic quantity' % item)
            else:
                return u.array([f[self.real_atom] for f in trajslice])
def test_pyscf_orbital_grid_works(h2_rhf_augccpvdz):
    """ Tests the basic input/output of the pyscf basis_values function

    Doesn't actually test the values directly - just that the answers are mathematically consistent
    """
    mol = h2_rhf_augccpvdz
    wfn = mol.wfn
    nbasis = len(wfn.aobasis)

    coords = u.array([mol.com,
                      np.zeros(3)*u.angstrom,
                      10.0 * np.ones(3) * u.angstrom,
                      np.ones(3)*u.nm])

    # First - check that the shape is appropriate if called without orbital coefficients
    values_nocoeffs = basis_values(mol, wfn.aobasis, coords)
    assert values_nocoeffs.shape == (len(coords), nbasis)
    assert (values_nocoeffs[-1] == values_nocoeffs[-2]).all()  # these 2 coordinates are the same

    # Second - explicitly send orbital coefficients for first 2 basis functions
    coeffs = np.zeros((2, nbasis))
    coeffs[:2, :2] = np.identity(2)
    vals_b0 = basis_values(mol, wfn.aobasis, coords, coeffs=coeffs)
    assert vals_b0.shape == (len(coords), len(coeffs))
    np.testing.assert_allclose(values_nocoeffs[:,:2], vals_b0)

    # Third - send symmetric and anti-symmetric combinations of basis functions and check answers
    plusminus = np.zeros((2, nbasis))
    plusminus[:2, :2] = 1.0 / np.sqrt(2)
    plusminus[1,1] = -1.0 / np.sqrt(2)
    vals_plusminus = basis_values(mol, wfn.aobasis, coords, coeffs=plusminus)
    assert vals_plusminus.shape == (len(coords), len(coeffs))
    helpers.assert_almost_equal(vals_plusminus[:,0],
                                (vals_b0[:,0] + vals_b0[:,1])/np.sqrt(2))
    helpers.assert_almost_equal(vals_plusminus[:,1],
                                (vals_b0[:,0] - vals_b0[:,1])/np.sqrt(2))
def test_container_properties(fixturename, request):
    obj = request.getfixturevalue(fixturename)
    assert obj.mass == sum([atom.mass for atom in obj.atoms])
    np.testing.assert_array_equal(obj.positions.defunits(),
                                  u.array([atom.position for atom in obj.atoms]).defunits())
    assert obj.num_atoms == len(obj.atoms)
def test_inconsistent_array_units_raises_dimensionality_error():
    with pytest.raises(units.DimensionalityError):
        u.array([[1, 2, 3] * u.angstrom, [3 * u.bohr, 4 * u.eV, 5 * u.bohr]])
示例#36
0
 def __get__(self, instance, owner):
     return u.array(
         [getattr(atom, self.attrname) for atom in instance.atoms])
def test_mixed_units_and_nonunits_raises_dimensionality_error():
    with pytest.raises(units.DimensionalityError):
        u.array([[1, 2, 3] * u.angstrom, [3 * u.bohr, 4, 5 * u.bohr]])
def test_no_nonsquare_arrays():
    with pytest.raises(ValueError):
        u.array([[1, 2], [3]])
 def __get__(self, instance, owner):
     return u.array([getattr(atom, self.attrname) for atom in instance.atoms])
示例#40
0
def parameterize(mol, charges='esp', ffname='gaff2', **kwargs):
    """Parameterize ``mol``, typically using GAFF parameters.

    This will both assign a forcefield to the molecule (at ``mol.ff``) and produce the parameters
    so that they can be used in other systems (e.g., so that this molecule can be simulated
    embedded in a larger protein)

    Note:
        'am1-bcc' and 'gasteiger' partial charges will be automatically computed if necessary.
        Other charge types must be precomputed.

    Args:
        mol (moldesign.Molecule):
        charges (str or dict): what partial charges to use? Can be a dict (``{atom:charge}``) OR
            a string, in which case charges will be read from
           ``mol.properties.[charges name]``; typical values will be 'esp', 'mulliken',
           'am1-bcc', etc. Use 'zero' to set all charges to 0 (for QM/MM and testing)
        ffname (str): Name of the gaff-like forcefield file (default: gaff2)

    Returns:
        ExtraAmberParameters: Parameters for the molecule; this object can be used to create
            forcefield parameters for other systems that contain this molecule
    """
    # Check that there's only 1 residue, give it a name
    assert mol.num_residues == 1
    if mol.residues[0].resname is None:
        mol.residues[0].resname = 'UNL'
        print 'Assigned residue name "UNL" to %s' % mol
    resname = mol.residues[0].resname

    # check that atoms have unique names
    if len(set(atom.name for atom in mol.atoms)) != mol.num_atoms:
        raise ValueError(
            'This molecule does not have uniquely named atoms, cannot assign FF'
        )

    if charges == 'am1-bcc' and 'am1-bcc' not in mol.properties:
        calc_am1_bcc_charges(mol)
    elif charges == 'gasteiger' and 'gasteiger' not in mol.properties:
        calc_gasteiger_charges(mol)

    if charges == 'zero':
        charge_array = [0.0 for atom in mol.atoms]
    elif isinstance(charges, basestring):
        charge_array = u.array(
            [mol.properties[charges][atom] for atom in mol.atoms])
        if not charge_array.dimensionless:  # implicitly convert floats to fundamental charge units
            charge_array = charge_array.to(u.q_e).magnitude
    else:
        charge_array = [charges[atom] for atom in mol.atoms]

    inputs = {
        'mol.mol2': mol.write(format='mol2'),
        'mol.charges': '\n'.join(map(str, charge_array))
    }

    cmds = [
        'antechamber -i mol.mol2 -fi mol2 -o mol_charged.mol2 '
        ' -fo mol2 -c rc -cf mol.charges -rn %s' % resname,
        'parmchk -i mol_charged.mol2 -f mol2 -o mol.frcmod',
        'tleap -f leap.in',
        'sed -e "s/tempresname/%s/g" mol_rename.lib > mol.lib' % resname
    ]

    inputs['leap.in'] = '\n'.join([
        "source leaprc.%s" % ffname, "tempresname = loadmol2 mol_charged.mol2",
        "fmod = loadamberparams mol.frcmod", "check tempresname",
        "saveoff tempresname mol_rename.lib",
        "saveamberparm tempresname mol.prmtop mol.inpcrd", "quit\n"
    ])

    def finish_job(j):
        param = ExtraAmberParameters(j.get_output('mol.lib'),
                                     j.get_output('mol.frcmod'), j)
        tempmol = mdt.assign_forcefield(mol, parameters=param)
        mol.ff = tempmol.ff
        return param

    job = pyccc.Job(image=mdt.compute.get_image_path(IMAGE),
                    command=' && '.join(cmds),
                    inputs=inputs,
                    when_finished=finish_job,
                    name="GAFF assignment: %s" % mol.name)

    return mdt.compute.run_job(job, _return_result=True, **kwargs)
        arr[3] = 5.0

    with pytest.raises(units.DimensionalityError):
        arr[:] = np.arange(5, 10) * units.fs

    arr[2:3] = np.arange(5, 6) * units.ureg.angstrom / units.ureg.fs
    np.testing.assert_allclose(arr[2:3].magnitude, np.arange(5, 6) / 10.0)

    arr[:] = np.arange(10,
                       15) * units.ureg.micrometers / units.ureg.picoseconds
    np.testing.assert_allclose(arr.magnitude, np.arange(10, 15))


@pytest.mark.parametrize(
    ['a1', 'a2'],
    ((np.ones(3), np.ones(3) * 10 / 10), (np.ones(3), u.array(np.ones(3))),
     (np.ones(3) * u.nm, 10.0 * np.ones(3) * u.angstrom), (np.ones(
         (3, 3)) * u.nm / u.angstrom, np.ones(3) * 10)),
    ids="numpy-numpy numpy-dimensionless nm-angstrom nm/angstrom-numpy".split(
    ))
def test_array_almost_equal_returns_true(a1, a2):
    assert u.arrays_almost_equal(a1, a2)
    assert u.arrays_almost_equal(a2, a1)


@pytest.mark.parametrize(
    ['a1', 'a2'], ((np.ones(3), np.ones(3) * 10 / 10 * u.eV),
                   (np.ones(3) * u.nm, 10.0 * np.ones(3) * u.dalton),
                   (u.array(np.ones(3)), np.ones(3) * u.kcalpermol)),
    ids="numpy-ev nm-dalton dimensionless-kcalpermole".split())
def test_array_almost_equal_raises_dimensionality_error(a1, a2):
def parameterize(mol, charges='esp', ffname='gaff2', **kwargs):
    """Parameterize ``mol``, typically using GAFF parameters.

    This will both assign a forcefield to the molecule (at ``mol.ff``) and produce the parameters
    so that they can be used in other systems (e.g., so that this molecule can be simulated
    embedded in a larger protein)

    Note:
        'am1-bcc' and 'gasteiger' partial charges will be automatically computed if necessary.
        Other charge types must be precomputed.

    Args:
        mol (moldesign.Molecule):
        charges (str or dict): what partial charges to use? Can be a dict (``{atom:charge}``) OR
            a string, in which case charges will be read from
           ``mol.properties.[charges name]``; typical values will be 'esp', 'mulliken',
           'am1-bcc', etc. Use 'zero' to set all charges to 0 (for QM/MM and testing)
        ffname (str): Name of the gaff-like forcefield file (default: gaff2)

    Returns:
        ExtraAmberParameters: Parameters for the molecule; this object can be used to create
            forcefield parameters for other systems that contain this molecule
    """
    # Check that there's only 1 residue, give it a name
    assert mol.num_residues == 1
    if mol.residues[0].resname is None:
        mol.residues[0].resname = 'UNL'
        print 'Assigned residue name "UNL" to %s' % mol
    resname = mol.residues[0].resname

    # check that atoms have unique names
    if len(set(atom.name for atom in mol.atoms)) != mol.num_atoms:
        raise ValueError('This molecule does not have uniquely named atoms, cannot assign FF')

    if charges == 'am1-bcc' and 'am1-bcc' not in mol.properties:
        calc_am1_bcc_charges(mol)
    elif charges == 'gasteiger' and 'gasteiger' not in mol.properties:
        calc_gasteiger_charges(mol)

    if charges == 'zero':
        charge_array = [0.0 for atom in mol.atoms]
    elif isinstance(charges, basestring):
        charge_array = u.array([mol.properties[charges][atom] for atom in mol.atoms])
        if not charge_array.dimensionless:  # implicitly convert floats to fundamental charge units
            charge_array = charge_array.to(u.q_e).magnitude
    else:
        charge_array = [charges[atom] for atom in mol.atoms]

    inputs = {'mol.mol2': mol.write(format='mol2'),
              'mol.charges': '\n'.join(map(str, charge_array))}

    cmds = ['antechamber -i mol.mol2 -fi mol2 -o mol_charged.mol2 '
                   ' -fo mol2 -c rc -cf mol.charges -rn %s' % resname,
            'parmchk -i mol_charged.mol2 -f mol2 -o mol.frcmod',
            'tleap -f leap.in',
            'sed -e "s/tempresname/%s/g" mol_rename.lib > mol.lib' % resname]

    inputs['leap.in'] = '\n'.join(["source leaprc.%s" % ffname,
                                   "tempresname = loadmol2 mol_charged.mol2",
                                   "fmod = loadamberparams mol.frcmod",
                                   "check tempresname",
                                   "saveoff tempresname mol_rename.lib",
                                   "saveamberparm tempresname mol.prmtop mol.inpcrd",
                                   "quit\n"])

    def finish_job(j):
        param = ExtraAmberParameters(j.get_output('mol.lib'),
                                     j.get_output('mol.frcmod'),
                                     j)
        tempmol = mdt.assign_forcefield(mol, parameters=param)
        mol.ff = tempmol.ff
        return param

    job = pyccc.Job(image=mdt.compute.get_image_path(IMAGE),
                    command=' && '.join(cmds),
                    inputs=inputs,
                    when_finished=finish_job,
                    name="GAFF assignment: %s" % mol.name)

    return mdt.compute.run_job(job, _return_result=True, **kwargs)