Skip to content

Commit

Permalink
Merge branch 'main' into cassandra-gmso
Browse files Browse the repository at this point in the history
  • Loading branch information
daico007 authored Sep 13, 2023
2 parents 2b0c7ee + 0c4c34c commit 8317de4
Show file tree
Hide file tree
Showing 14 changed files with 269 additions and 77 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/CI.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ jobs:
matrix:
os: [macOS-latest, ubuntu-latest]
python-version: ["3.8", "3.9", "3.10", "3.11"]
pydantic-version: ["1", "2"]
pydantic-version: ["2"]

defaults:
run:
Expand Down
1 change: 1 addition & 0 deletions codecov.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@ ignore:
- "gmso/examples"
- "gmso/tests"
- "gmso/formats/networkx.py"
- "gmso/external/convert_foyer_xml.py"
4 changes: 2 additions & 2 deletions docs/installation.rst
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,8 @@ Once all dependencies have been installed and the ``conda`` environment has been
Supported Python Versions
-------------------------

Python 3.7 is the recommend version for users. It is the only version on which
development and testing consistently takes place. Older (3.6) and newer (3.8+)
Python 3.8-3.11 is the recommend version for users. It is the only version on which
development and testing consistently takes place. Older (3.6-3.7) and newer (3.12+)
versions of Python 3 are likely to work but no guarantee is made and, in
addition, some dependencies may not be available for other versions. No effort
is made to support Python 2 because it is considered obsolete as of early 2020.
Expand Down
35 changes: 25 additions & 10 deletions gmso/core/forcefield.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,19 @@

from lxml import etree

try:
from pydantic.v1 import ValidationError
except:
from pydantic import ValidationError

from gmso.core.element import element_by_symbol
from gmso.exceptions import GMSOError, MissingPotentialError
from gmso.exceptions import (
ForceFieldParseError,
GMSOError,
MissingPotentialError,
)
from gmso.utils._constants import FF_TOKENS_SEPARATOR
from gmso.utils.decorators import deprecate_kwargs
from gmso.utils.decorators import deprecate_function, deprecate_kwargs
from gmso.utils.ff_utils import (
parse_ff_atomtypes,
parse_ff_connection_types,
Expand Down Expand Up @@ -45,10 +54,8 @@ class ForceField(object):
Parameters
----------
name : str
Name of the forcefield, default 'ForceField'
version : str
a cannonical semantic version of the forcefield, default 1.0.0
xml_loc : str
Path to the forcefield xml. The forcefield xml can be either in Foyer or GMSO style.
strict: bool, default=True
If true, perform a strict validation of the forcefield XML file
greedy: bool, default=True
Expand Down Expand Up @@ -104,6 +111,7 @@ def __init__(
"ffutils",
]:
ff = ForceField.xml_from_forcefield_utilities(xml_loc)

else:
raise (
GMSOError(
Expand Down Expand Up @@ -565,10 +573,14 @@ def __eq__(self, other):

@classmethod
def xml_from_forcefield_utilities(cls, filename):
from forcefield_utilities.xml_loader import GMSOFFs

loader = GMSOFFs()
ff = loader.load(filename).to_gmso_ff()
from forcefield_utilities.xml_loader import FoyerFFs, GMSOFFs

try:
loader = GMSOFFs()
ff = loader.load(filename).to_gmso_ff()
except (ForceFieldParseError, FileNotFoundError, ValidationError):
loader = FoyerFFs()
ff = loader.load(filename).to_gmso_ff()
return ff

def to_xml(self, filename, overwrite=False, backend="gmso"):
Expand Down Expand Up @@ -723,6 +735,9 @@ def _xml_from_gmso(self, filename, overwrite=False):
)

@classmethod
@deprecate_function(
"The internal `from_xml` will be deprecated soon. Please load the XML with the `xml_from_forcefield_utilities`."
)
def from_xml(cls, xmls_or_etrees, strict=True, greedy=True):
"""Create a gmso.Forcefield object from XML File(s).
Expand Down
94 changes: 93 additions & 1 deletion gmso/core/topology.py
Original file line number Diff line number Diff line change
Expand Up @@ -647,6 +647,61 @@ def get_scaling_factors(self, *, molecule_id=None):
]
)

def remove_site(self, site):
"""Remove a site from the topology.
Parameters
----------
site : gmso.core.Site
The site to be removed.
Notes
-----
When a site is removed, any connections that site belonged
to are also removed.
See Also
--------
gmso.core.topology.Topology.iter_connections_by_site
The method that shows all connections belonging to a specific site
"""
if site not in self._sites:
raise ValueError(
f"Site {site} is not currently part of this topology."
)
site_connections = [
conn for conn in self.iter_connections_by_site(site)
]
for conn in site_connections:
self.remove_connection(conn)
self._sites.remove(site)

def remove_connection(self, connection):
"""Remove a connection from the topology.
Parameters
----------
connection : gmso.abc.abstract_conneciton.Connection
The connection to be removed from the topology
Notes
-----
The sites that belong to this connection are
not removed from the topology.
"""
if connection not in self.connections:
raise ValueError(
f"Connection {connection} is not currently part of this topology."
)
if isinstance(connection, gmso.core.bond.Bond):
self._bonds.remove(connection)
elif isinstance(connection, gmso.core.angle.Angle):
self._angles.remove(connection)
elif isinstance(connection, gmso.core.dihedral.Dihedral):
self._dihedrals.remove(connection)
elif isinstance(connection, gmso.core.improper.Improper):
self._impropers.remove(connection)

def set_scaling_factors(self, lj, electrostatics, *, molecule_id=None):
"""Set both lj and electrostatics scaling factors."""
self.set_lj_scale(
Expand Down Expand Up @@ -831,7 +886,6 @@ def add_connection(self, connection, update_types=False):
Improper: self._impropers,
}
connections_sets[type(connection)].add(connection)

if update_types:
self.update_topology()

Expand Down Expand Up @@ -1367,6 +1421,44 @@ def iter_sites_by_molecule(self, molecule_tag):
else:
return self.iter_sites("molecule", molecule_tag)

def iter_connections_by_site(self, site, connections=None):
"""Iterate through this topology's connections which contain
this specific site.
Parameters
----------
site : gmso.core.Site
Site to limit connections search to.
connections : set or list or tuple, optional, default=None
The connection types to include in the search.
If None, iterates through all of a site's connections.
Options include "bonds", "angles", "dihedrals", "impropers"
Yields
------
gmso.abc.abstract_conneciton.Connection
Connection where site is in Connection.connection_members
"""
if site not in self._sites:
raise ValueError(
f"Site {site} is not currently part of this topology."
)
if connections is None:
connections = ["bonds", "angles", "dihedrals", "impropers"]
else:
connections = set([option.lower() for option in connections])
for option in connections:
if option not in ["bonds", "angles", "dihedrals", "impropers"]:
raise ValueError(
"Valid connection types are limited to: "
'"bonds", "angles", "dihedrals", "impropers"'
)
for conn_str in connections:
for conn in getattr(self, conn_str):
if site in conn.connection_members:
yield conn

def create_subtop(self, label_type, label):
"""Create a new Topology object from a molecule or graup of the current Topology.
Expand Down
1 change: 0 additions & 1 deletion gmso/external/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
"""Support for various in-memory representations of chemical systems."""
from .convert_foyer_xml import from_foyer_xml
from .convert_hoomd import (
to_gsd_snapshot,
to_hoomd_forcefield,
Expand Down
4 changes: 4 additions & 0 deletions gmso/external/convert_foyer_xml.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,12 @@
from lxml import etree

from gmso.exceptions import ForceFieldParseError
from gmso.utils.decorators import deprecate_function


@deprecate_function(
"The `from_foyer_xml` method will be deprecated soon. Please use the package `forcefield-utilities.FoyerFFs`."
)
def from_foyer_xml(
foyer_xml, gmso_xml=None, overwrite=False, validate_foyer=False
):
Expand Down
34 changes: 6 additions & 28 deletions gmso/tests/base_test.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import forcefield_utilities as ffutils
import foyer
import mbuild as mb
import numpy as np
Expand All @@ -17,7 +16,6 @@
from gmso.core.pairpotential_type import PairPotentialType
from gmso.core.topology import Topology
from gmso.external import from_mbuild, from_parmed
from gmso.external.convert_foyer_xml import from_foyer_xml
from gmso.parameterization import apply
from gmso.tests.utils import get_path
from gmso.utils.io import get_fn
Expand Down Expand Up @@ -74,11 +72,7 @@ def benzene_ua_box(self):
@pytest.fixture
def typed_benzene_ua_system(self, benzene_ua_box):
top = benzene_ua_box
trappe_benzene = (
ffutils.FoyerFFs()
.load(get_path("benzene_trappe-ua.xml"))
.to_gmso_ff()
)
trappe_benzene = ForceField(get_path("benzene_trappe-ua.xml"))
top = apply(top=top, forcefields=trappe_benzene, remove_untyped=True)
return top

Expand All @@ -104,7 +98,7 @@ def benzene_aa_box(self):
@pytest.fixture
def typed_benzene_aa_system(self, benzene_aa_box):
top = benzene_aa_box
oplsaa = ffutils.FoyerFFs().load("oplsaa").to_gmso_ff()
oplsaa = ForceField("oplsaa")
top = apply(top=top, forcefields=oplsaa, remove_untyped=True)
return top

Expand Down Expand Up @@ -281,41 +275,25 @@ def typed_tip3p_rigid_system(self, water_system):
def foyer_fullerene(self):
from foyer.tests.utils import get_fn

from_foyer_xml(get_fn("fullerene.xml"), overwrite=True)
gmso_ff = ForceField("fullerene_gmso.xml")

return gmso_ff
return ForceField(get_fn("fullerene.xml"))

@pytest.fixture
def foyer_periodic(self):
# TODO: this errors out with backend="ffutils"
from foyer.tests.utils import get_fn

from_foyer_xml(get_fn("oplsaa-periodic.xml"), overwrite=True)
gmso_ff = ForceField("oplsaa-periodic_gmso.xml", backend="gmso")

return gmso_ff
return ForceField(get_fn("oplsaa-periodic.xml"))

@pytest.fixture
def foyer_urey_bradley(self):
# TODO: this errors out with backend="ffutils"
from foyer.tests.utils import get_fn

from_foyer_xml(get_fn("charmm36_cooh.xml"), overwrite=True)
gmso_ff = ForceField("charmm36_cooh_gmso.xml", backend="gmso")

return gmso_ff
return ForceField(get_fn("charmm36_cooh.xml"))

@pytest.fixture
def foyer_rb_torsion(self):
from foyer.tests.utils import get_fn

from_foyer_xml(
get_fn("refs-multi.xml"), overwrite=True, validate_foyer=True
)
gmso_ff = ForceField("refs-multi_gmso.xml")

return gmso_ff
return ForceField(get_fn("refs-multi.xml"))

@pytest.fixture
def methane(self):
Expand Down
Loading

0 comments on commit 8317de4

Please sign in to comment.