Skip to content

Commit

Permalink
create internal module, add doc for utils
Browse files Browse the repository at this point in the history
  • Loading branch information
chrisjonesBSU committed Jan 19, 2024
1 parent 15e0581 commit 6146a4d
Show file tree
Hide file tree
Showing 18 changed files with 126 additions and 116 deletions.
2 changes: 1 addition & 1 deletion .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -43,5 +43,5 @@ repos:
rev: '6.3.0'
hooks:
- id: pydocstyle
exclude: ^(flowermd/tests/|flowermd/utils/|setup.py|flowermd/__version__.py|docs/)
exclude: ^(flowermd/tests/|flowermd/internal/|flowermd/utils|setup.py|flowermd/__version__.py|docs/)
args: [ --convention=numpy ]
Binary file added docs/source/.library.rst.swp
Binary file not shown.
Binary file added docs/source/.utils.rst.swp
Binary file not shown.
1 change: 1 addition & 0 deletions docs/source/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ Resources
base
modules
library
utils



Expand Down
11 changes: 11 additions & 0 deletions docs/source/utils.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
Utils
=======

.. rubric:: Overview

.. py:currentmodule:: flowermd.utils
.. rubric:: Utils

.. automodule:: flowermd.utils
:members:
6 changes: 3 additions & 3 deletions flowermd/base/molecule.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,9 @@
from mbuild.lib.recipes import Polymer as mbPolymer

from flowermd.base import BaseHOOMDForcefield, BaseXMLForcefield
from flowermd.utils import check_return_iterable
from flowermd.utils.exceptions import ForceFieldError, MoleculeLoadError
from flowermd.utils.ff_utils import _validate_hoomd_ff
from flowermd.internal import check_return_iterable
from flowermd.internal.exceptions import ForceFieldError, MoleculeLoadError
from flowermd.internal.ff_utils import _validate_hoomd_ff


class Molecule:
Expand Down
9 changes: 3 additions & 6 deletions flowermd/base/simulation.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,9 @@
import numpy as np
import unyt as u

from flowermd.utils import (
HOOMDThermostats,
StdOutLogger,
UpdateWalls,
validate_ref_value,
)
from flowermd.internal import validate_ref_value
from flowermd.utils.actions import StdOutLogger, UpdateWalls
from flowermd.utils.base_types import HOOMDThermostats


class Simulation(hoomd.simulation.Simulation):
Expand Down
5 changes: 2 additions & 3 deletions flowermd/base/system.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,12 @@

from flowermd.base.forcefield import BaseHOOMDForcefield, BaseXMLForcefield
from flowermd.base.molecule import Molecule
from flowermd.internal import check_return_iterable, validate_ref_value
from flowermd.internal.exceptions import ForceFieldError, MoleculeLoadError
from flowermd.utils import (
check_return_iterable,
get_target_box_mass_density,
get_target_box_number_density,
validate_ref_value,
)
from flowermd.utils.exceptions import ForceFieldError, MoleculeLoadError


class System(ABC):
Expand Down
2 changes: 2 additions & 0 deletions flowermd/internal/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
from .ff_utils import xml_to_gmso_ff
from .utils import check_return_iterable, validate_ref_value
File renamed without changes.
File renamed without changes.
95 changes: 95 additions & 0 deletions flowermd/internal/utils.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
import unyt as u

from flowermd.internal.exceptions import ReferenceUnitError

"""utils.py
Internal utility methods for flowerMD.
"""


def check_return_iterable(obj):
if isinstance(obj, dict):
return [obj]
if isinstance(obj, str):
return [obj]
try:
iter(obj)
return obj
except: # noqa: E722
return [obj]


def validate_ref_value(ref_value, dimension):
"""Validate the reference value and checks the unit dimension.
This function validates the reference value. The reference value can be
provided in three ways:
1. An unyt_quantity instance.
2. A string with the value and unit , for example "1.0 g".
3. A string with the value and unit separated by a "/", for example
"1.0 kcal/mol".
Parameters
----------
ref_value : unyt_quantity or str; required
The reference value.
dimension : unyt_dimension; required
The dimension of the reference value.
Returns
-------
The validated reference value as an unyt.unyt_quantity instance.
"""

def _is_valid_dimension(ref_unit):
if ref_unit.dimensions != dimension:
raise ReferenceUnitError(
f"Invalid unit dimension. The reference "
f"value must be in {dimension} "
f"dimension."
)
return True

def _parse_and_validate_unit(value, unit_str):
if hasattr(u, unit_str):
if unit_str == "amu":
u_unit = u.Unit("amu")
else:
u_unit = getattr(u, unit_str)
if _is_valid_dimension(u_unit):
return float(value) * u_unit
# if the unit contains "/" character, for example "g/mol", check if
# the unit is a valid unit and has the correct dimension.
if len(unit_str.split("/")) == 2:
unit1, unit2 = unit_str.split("/")
if hasattr(u, unit1) and hasattr(u, unit2):
comb_unit = getattr(u, unit1) / getattr(u, unit2)
if _is_valid_dimension(comb_unit):
return float(value) * comb_unit
raise ReferenceUnitError(
f"Invalid reference value. Please provide "
f"a reference value with unit of "
f"{dimension} dimension."
)

def _is_float(num):
try:
return float(num)
except ValueError:
raise ValueError("The reference value is not a number.")

# if ref_value is an instance of unyt_quantity, check the dimension.
if isinstance(ref_value, u.unyt_quantity) and _is_valid_dimension(
ref_value.units
):
return ref_value
# if ref_value is a string, check if it is a number and if it is, check if
# the unit exists in unyt and has the correct dimension.
elif isinstance(ref_value, str) and len(ref_value.split()) == 2:
value, unit_str = ref_value.split()
value = _is_float(value)
return _parse_and_validate_unit(value, unit_str)
else:
raise ReferenceUnitError(
f"Invalid reference value. Please provide "
f"a reference value with unit of "
f"{dimension} dimension."
)
2 changes: 1 addition & 1 deletion flowermd/tests/base/test_molecule.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@
from cmeutils.geometry import get_backbone_vector

from flowermd import CoPolymer, Molecule, Polymer
from flowermd.internal import exceptions
from flowermd.library import OPLS_AA, BeadSpring, FF_from_file
from flowermd.tests import BaseTest
from flowermd.utils import exceptions


class TestMolecule(BaseTest):
Expand Down
2 changes: 1 addition & 1 deletion flowermd/tests/base/test_system.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@
from unyt import Unit

from flowermd import Lattice, Pack
from flowermd.internal.exceptions import ForceFieldError, ReferenceUnitError
from flowermd.library import OPLS_AA, OPLS_AA_DIMETHYLETHER, OPLS_AA_PPS
from flowermd.tests import BaseTest
from flowermd.utils.exceptions import ForceFieldError, ReferenceUnitError


class TestSystem(BaseTest):
Expand Down
Binary file added flowermd/utils/.utils.py.swp
Binary file not shown.
9 changes: 1 addition & 8 deletions flowermd/utils/__init__.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,3 @@
from .actions import *
from .base_types import HOOMDThermostats
from .ff_utils import xml_to_gmso_ff
from .utils import (
_calculate_box_length,
check_return_iterable,
get_target_box_mass_density,
get_target_box_number_density,
validate_ref_value,
)
from .utils import get_target_box_mass_density, get_target_box_number_density
96 changes: 3 additions & 93 deletions flowermd/utils/utils.py
Original file line number Diff line number Diff line change
@@ -1,109 +1,19 @@
import numpy as np
import unyt as u

from flowermd.utils.exceptions import ReferenceUnitError

"""utils.py
utility methods for flowerMD.
"""


def check_return_iterable(obj):
if isinstance(obj, dict):
return [obj]
if isinstance(obj, str):
return [obj]
try:
iter(obj)
return obj
except: # noqa: E722
return [obj]


def validate_ref_value(ref_value, dimension):
"""Validates the reference value and checks the unit dimension.
This function validates the reference value. The reference value can be
provided in three ways:
1. An unyt_quantity instance.
2. A string with the value and unit , for example "1.0 g".
3. A string with the value and unit separated by a "/", for example
"1.0 kcal/mol".
Parameters
----------
ref_value : unyt_quantity or str; required
The reference value.
dimension : unyt_dimension; required
The dimension of the reference value.
Returns
-------
The validated reference value as an unyt.unyt_quantity instance.
"""

def _is_valid_dimension(ref_unit):
if ref_unit.dimensions != dimension:
raise ReferenceUnitError(
f"Invalid unit dimension. The reference "
f"value must be in {dimension} "
f"dimension."
)
return True

def _parse_and_validate_unit(value, unit_str):
if hasattr(u, unit_str):
if unit_str == "amu":
u_unit = u.Unit("amu")
else:
u_unit = getattr(u, unit_str)
if _is_valid_dimension(u_unit):
return float(value) * u_unit
# if the unit contains "/" character, for example "g/mol", check if
# the unit is a valid unit and has the correct dimension.
if len(unit_str.split("/")) == 2:
unit1, unit2 = unit_str.split("/")
if hasattr(u, unit1) and hasattr(u, unit2):
comb_unit = getattr(u, unit1) / getattr(u, unit2)
if _is_valid_dimension(comb_unit):
return float(value) * comb_unit
raise ReferenceUnitError(
f"Invalid reference value. Please provide "
f"a reference value with unit of "
f"{dimension} dimension."
)

def _is_float(num):
try:
return float(num)
except ValueError:
raise ValueError("The reference value is not a number.")

# if ref_value is an instance of unyt_quantity, check the dimension.
if isinstance(ref_value, u.unyt_quantity) and _is_valid_dimension(
ref_value.units
):
return ref_value
# if ref_value is a string, check if it is a number and if it is, check if
# the unit exists in unyt and has the correct dimension.
elif isinstance(ref_value, str) and len(ref_value.split()) == 2:
value, unit_str = ref_value.split()
value = _is_float(value)
return _parse_and_validate_unit(value, unit_str)
else:
raise ReferenceUnitError(
f"Invalid reference value. Please provide "
f"a reference value with unit of "
f"{dimension} dimension."
)


def get_target_box_mass_density(
density,
mass,
x_constraint=None,
y_constraint=None,
z_constraint=None,
):
"""Helper function to calculate box lengths that match a given mass density.
"""Utility for calculating box lengths that match a given mass density.
If no constraints are set, the target box is cubic.
Setting constraints will hold those box vectors
Expand Down Expand Up @@ -147,7 +57,7 @@ def get_target_box_number_density(
y_constraint=None,
z_constraint=None,
):
"""Helper function to calculate box lengths that match a given number
"""Utility for calculating box lengths that match a given number
density.
If no constraints are set, the target box is cubic.
Expand Down Expand Up @@ -187,7 +97,7 @@ def get_target_box_number_density(


def _calculate_box_length(density, mass=None, n_beads=None, fixed_L=None):
"""Helper function to calculate box lengths that match a given density.
"""Calculates box lengths that match a given density.
See `flowermd.utils.get_target_box_mass_density` and
`flowermd.utils.get_target_box_number_density`
Expand Down
2 changes: 2 additions & 0 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,8 @@ def run(self):
"library/**",
"assets/forcefields/*",
"assets/molecule_files/*",
"utils/**",
"internal/**",
]
},
install_requires=REQUIRED,
Expand Down

0 comments on commit 6146a4d

Please sign in to comment.