Skip to content

Commit

Permalink
Merge branch 'main' into 563-box-enh
Browse files Browse the repository at this point in the history
  • Loading branch information
daico007 authored Mar 15, 2024
2 parents 6fefa5c + 69fd5e2 commit 2d605cc
Show file tree
Hide file tree
Showing 102 changed files with 2,766 additions and 913 deletions.
18 changes: 8 additions & 10 deletions .github/workflows/CI.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,7 @@ jobs:
fail-fast: false
matrix:
os: [macOS-latest, ubuntu-latest]
python-version: ["3.8", "3.9", "3.10", "3.11"]
pydantic-version: ["2"]
python-version: ["3.9", "3.10", "3.11"]

defaults:
run:
Expand All @@ -36,7 +35,6 @@ jobs:
environment-file: environment-dev.yml
create-args: >-
python=${{ matrix.python-version }}
pydantic=${{ matrix.pydantic-version }}
- name: Install Package
run: python -m pip install -e .
Expand Down Expand Up @@ -66,7 +64,7 @@ jobs:
uses: mamba-org/setup-micromamba@v1
with:
environment-file: environment-dev.yml
python-version: python="3.10"
create-args: python=3.10

- name: Clone mBuild and Foyer and forcefield-utilities
run: |
Expand Down Expand Up @@ -95,34 +93,34 @@ jobs:
runs-on: ubuntu-latest
needs: test
name: Build Docker Image
if: ${{ false }}
if: github.event_name != 'pull_request'

steps:
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v1
uses: docker/setup-buildx-action@v3

- name: Login to DockerHub
uses: docker/login-action@v1
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_PASSWORD }}

- name: Get Tagged Version
run: |
echo "DOCKER_TAGS=mosdef-gmso-${CI_COMMIT_REF_SLUG}, mosdef-gmso-stable" >> $GITHUB_ENV
echo "DOCKER_TAGS=mosdef/gmso:${GITHUB_REF_NAME}, mosdef/gmso:stable" >> $GITHUB_ENV
if: github.ref_type == 'tag'

- name: Get Push Version
run: |
echo "DOCKER_TAGS=mosdef-gmso-${CI_COMMIT_REF_SLUG}, mosdef-gmso-latest" >> $GITHUB_ENV
echo "DOCKER_TAGS=mosdef/gmso:${GITHUB_REF_NAME}, mosdef/gmso:latest" >> $GITHUB_ENV
if: github.ref_type == 'branch'

- name: Docker Image Info
run: |
echo Docker Image tags: ${DOCKER_TAGS}
- name: Build and Push
uses: docker/build-push-action@v2
uses: docker/build-push-action@v5
with:
push: true
tags: ${{ env.DOCKER_TAGS }}
6 changes: 3 additions & 3 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -9,19 +9,19 @@ ci:
submodules: false
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.4.0
rev: v4.5.0
hooks:
- id: check-yaml
- id: end-of-file-fixer
- id: trailing-whitespace
exclude: 'setup.cfg|gmso/tests/files/.*'
- repo: https://github.com/psf/black
rev: 23.9.1
rev: 24.2.0
hooks:
- id: black
args: [--line-length=80]
- repo: https://github.com/pycqa/isort
rev: 5.12.0
rev: 5.13.2
hooks:
- id: isort
name: isort (python)
Expand Down
36 changes: 27 additions & 9 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
FROM mambaorg/micromamba:1.4.3
ARG PY_VERSION=3.10
FROM continuumio/miniconda3:4.10.3-alpine AS builder

EXPOSE 8888

Expand All @@ -13,17 +14,34 @@ ADD . /gmso

WORKDIR /gmso

RUN apt-get update && apt-get install -y git
# Create a group and user
RUN addgroup -S anaconda && adduser -S anaconda -G anaconda

RUN apk update && apk add libarchive &&\
conda update conda -yq && \
conda config --set always_yes yes --set changeps1 no && \
. /opt/conda/etc/profile.d/conda.sh && \
sed -i -E "s/python.*$/python="$(PY_VERSION)"/" environment-dev.yml && \
conda install -c conda-forge mamba && \
mamba env create --file environment-dev.yml && \
conda activate gmso-dev && \
mamba install -c conda-forge jupyter python="$PY_VERSION" && \
python setup.py install && \
echo "source activate gmso-dev" >> \
/home/anaconda/.profile && \
conda clean -afy && \
mkdir -p /home/anaconda/data && \
chown -R anaconda:anaconda /gmso && \
chown -R anaconda:anaconda /opt && \
chown -R anaconda:anaconda /home/anaconda

RUN micromamba create --file environment-dev.yml && \
micromamba clean -afy
ARG MAMBA_DOCKERFILE_ACTIVATE=1 # (otherwise python will not be found)
WORKDIR /home/anaconda

RUN micromamba install -c conda-forge nomkl jupyter python="3.10" && \
python setup.py install && \
echo "source activate gmso-dev" >> /home/.bashrc && \
mkdir -p /home/data
COPY devtools/docker-entrypoint.sh /entrypoint.sh

RUN chmod a+x /entrypoint.sh

USER anaconda

ENTRYPOINT ["/entrypoint.sh"]
CMD ["jupyter"]
1 change: 1 addition & 0 deletions codecov.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
ignore:
- "gmso/examples"
- "gmso/tests"
- "gmso/paper"
- "gmso/formats/networkx.py"
- "gmso/external/convert_foyer_xml.py"
4 changes: 2 additions & 2 deletions docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@
author = "Matt Thompson, Alex Yang, Ray Matsumoto, Parashara Shamaprasad, Umesh Timalsina, Co Quach, Ryan S. DeFever, Justin Gilmer"

# The full version, including alpha/beta/rc tags
version = "0.11.2"
release = "0.11.2"
version = "0.12.0"
release = "0.12.0"


# -- General configuration ---------------------------------------------------
Expand Down
71 changes: 68 additions & 3 deletions docs/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,75 @@
GMSO: Flexible storage of chemical topology for molecular simulation
====================================================================
`GMSO`is a flexible storage of chemical topology for molecular simulation.
With a few lines of `GMSO` code, together with [`mBuild`](https://mbuild.mosdef.org) and [`foyer`](https://foyer.mosdef.org), users can rapidly prototype arbitrary parameterized chemical systems and generate data files for a wide variety of simulation engines.


GMSO is a part of the MoSDeF ecosystem
-----------------------------------------
`GMSO` is designed to be a general and flexible representation of chemical topolgies for molecular simulation.
With an emphasis on assuming as little as possible about the chemical system, model, or engine, `GMSO` can enable support for a variety of systems.
`GMSO` is a part of the [MoSDeF (Molecular Simulation and Design Framework)](https://mosdef.org) ecosystem, and is intended to be the backend replacement for the [`foyer` package](https://foyer.mosdef.org).
Libraries in the MoSDeF ecosystem are designed to provide utilities neccessary to streamline
a researcher's simulation workflow. When setting up simulation studies,
we also recommend users to follow the [TRUE](https://www.tandfonline.com/doi/full/10.1080/00268976.2020.1742938)
(Transparent, Reproducible, Usable-by-others, and Extensible) standard, which is a set of common
practices meant to improve the reproducibility of computational simulation research.


Goals and Features
------------------

`GMSO`'s goal is to provide a flexible backend framework to store topological information of a chemical system in a reproducible fashion.
**Topology** in this case is defined as the information needed to initialize a molecular simulation.
Depending on the type of simulation performed, this ranges from:
* particle positions
* particle connectivity
* box information
* forcefield data
- functional forms defined as [`sympy` expressions](https://www.sympy.org)
- parameters with defined units
- partial charges
- tabulated data
- etc.
* Other optional data
- particle mass
- elemental data
- etc.

With these driving goals for `GMSO`, the following features are enabled:
1. __Supporting a variety of models__ in the molecular simulation/computational
chemistry community_:
No assumptions are made about an interaction site
representing an atom or bead, instead these can be atomistic,
united-atom/coarse-grained, polarizable, and other models!

1. __Greater flexibility for exotic potentials__: The [`AtomType`](./gmso/core/atom_type.py) (and [analogue
classes for intramolecular interactions](./gmso/core)) uses [`sympy`](https://www.sympy.org) to store any
potential that can be represented by a mathematical expression.

1. __Adaptable for new engines__: by not being designed for
compatibility with any particular molecular simulation engine or ecosystem,
it becomes more tractable for developers in the community to add glue for
engines that are not currently supported.

1. __Compatibility with existing community tools__: No single molecular simulation
tool will ever be a silver bullet, so ``GMSO`` includes functions to convert
between various file formats and libraries. These can be used in their own right to convert between objects in-memory
and also to support conversion to file formats not natively supported at
any given time. Currently supported conversions include:
* [`ParmEd`](./gmso/external/convert_parmed.py)
* [`OpenMM`](./gmso/external/convert_openmm.py)
* [`mBuild`](./gmso/external/convert_mbuild.py)
* more in the future!

1. __Native support for reading and writing many common file formats__: We natively have support for:
* [`XYZ`](./gmso/formats/xyz.py)
* [`GRO`](./gmso/formats/gro.py)
* [`TOP`](gmso/formats/top.py)
* [`LAMMPSDATA`](gmso/formats/lammpsdata.py)
* indirect support, through other libraries, for many more!

This is the documentation for ``GMSO``, the General Molecular Simulation Object.
It is a part of the `MoSDeF <http://mosdef.org>`_, the Molecular Simulation
Design Framework.

.. toctree::
:hidden:
Expand Down
2 changes: 1 addition & 1 deletion environment-dev.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ dependencies:
- unyt>=2.9.5
- boltons
- lxml
- pydantic
- pydantic>=2
- networkx
- pytest
- mbuild>=0.11.0
Expand Down
2 changes: 1 addition & 1 deletion environment.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ dependencies:
- unyt>=2.9.5
- boltons
- lxml
- pydantic
- pydantic>=2
- networkx
- ele >= 0.2.0
- molbox
Expand Down
3 changes: 2 additions & 1 deletion gmso/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
"""GMSO: General Molecular Simulation Object."""

from .core.angle import Angle
from .core.angle_type import AngleType
from .core.atom import Atom
Expand All @@ -15,4 +16,4 @@
from .core.pairpotential_type import PairPotentialType
from .core.topology import Topology

__version__ = "0.11.2"
__version__ = "0.12.0"
2 changes: 1 addition & 1 deletion gmso/abc/__init__.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
from gmso.abc.serialization_utils import GMSOJSONHandler, unyt_to_dict
from gmso.abc.serialization_utils import unyt_to_dict
47 changes: 25 additions & 22 deletions gmso/abc/abstract_connection.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,11 @@
from typing import Optional, Sequence

from pydantic import ConfigDict, Field, model_validator

from gmso.abc.abstract_site import Site
from gmso.abc.gmso_base import GMSOBase
from gmso.exceptions import GMSOError

try:
from pydantic.v1 import Field, root_validator
except ImportError:
from pydantic import Field, root_validator


class Connection(GMSOBase):
__base_doc__ = """An abstract class that stores data about connections between sites.
Expand All @@ -18,12 +15,21 @@ class Connection(GMSOBase):
"""

name_: str = Field(
default="", description="Name of the connection. Defaults to class name"
default="",
description="Name of the connection. Defaults to class name.",
alias="name",
)

connection_members_: Optional[Sequence[Site]] = Field(
default=None,
description="A list of constituents in this connection, in order.",
alias="connection_members",
)
model_config = ConfigDict(
alias_to_fields={
"name": "name_",
"connection_members": "connection_members_",
}
)

@property
Expand All @@ -37,12 +43,12 @@ def name(self):
@property
def member_types(self):
"""Return the atomtype of the connection members as a list of string."""
return self._get_members_types_or_classes("member_types_")
return self._get_members_types_or_classes("member_types")

@property
def member_classes(self):
"""Return the class of the connection members as a list of string."""
return self._get_members_types_or_classes("member_classes_")
return self._get_members_types_or_classes("member_classes")

def _has_typed_members(self):
"""Check if all the members of this connection are typed."""
Expand All @@ -53,24 +59,29 @@ def _has_typed_members(self):

def _get_members_types_or_classes(self, to_return):
"""Return types or classes for connection members if they exist."""
assert to_return in {"member_types_", "member_classes_"}
assert to_return in {"member_types", "member_classes"}
ctype = getattr(self, "connection_type")
ctype_attr = getattr(ctype, to_return) if ctype else None

if ctype_attr:
return list(ctype_attr)
elif self._has_typed_members():
tc = [
member.atom_type.name
if to_return == "member_types_"
else member.atom_type.atomclass
(
member.atom_type.name
if to_return == "member_types"
else member.atom_type.atomclass
)
for member in self.__dict__.get("connection_members_")
]
return tc if all(tc) else None

@root_validator(pre=True)
@model_validator(mode="before")
def validate_fields(cls, values):
connection_members = values.get("connection_members")
if "connection_members" in values:
connection_members = values.get("connection_members")
else:
connection_members = values.get("connection_members_")

if all(isinstance(member, dict) for member in connection_members):
connection_members = [
Expand Down Expand Up @@ -103,11 +114,3 @@ def __repr__(self):

def __str__(self):
return f"<{self.__class__.__name__} {self.name}, id: {id(self)}> "

class Config:
fields = {"name_": "name", "connection_members_": "connection_members"}

alias_to_fields = {
"name": "name_",
"connection_members": "connection_members_",
}
Loading

0 comments on commit 2d605cc

Please sign in to comment.