diff --git a/.github/workflows/BranchCI.yaml b/.github/workflows/BranchCI.yaml index 482a7bf..165d007 100644 --- a/.github/workflows/BranchCI.yaml +++ b/.github/workflows/BranchCI.yaml @@ -4,7 +4,6 @@ on: push: branches-ignore: - 'main' - - 'master' jobs: light-ci: @@ -51,10 +50,4 @@ jobs: file: ./coverage.xml flags: unittests name: codecov-ubuntu-latest-py3.8 - - name: Build documentation - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - shell: bash -l {0} - run: | - docs/buildDocs.sh diff --git a/.github/workflows/CI.yaml b/.github/workflows/CI.yaml index 0dc6e83..d7657ce 100644 --- a/.github/workflows/CI.yaml +++ b/.github/workflows/CI.yaml @@ -1,26 +1,21 @@ name: CI on: - # GitHub has started calling new repo's first branch "main" https://github.com/github/renaming - # Existing codes likely still have "master" as the primary branch - # Both are tracked here to keep legacy and new codes working push: branches: - - "master" - "main" pull_request: branches: - - "master" - "main" schedule: - # Run on master by default Sunday morning at 3:30: + # Run by default Sunday morning at 3:30: # Scheduled workflows run on the latest commit on the default or base branch. # (from https://help.github.com/en/actions/reference/events-that-trigger-workflows#scheduled-events-schedule) - cron: "30 3 * * 0" jobs: - lint-docs: - name: Lint-Docs ubuntu-latest Py3.8 + lint: + name: Lint ubuntu-latest Py3.8 runs-on: ubuntu-latest steps: - uses: actions/checkout@v1 @@ -53,17 +48,11 @@ jobs: run: | flake8 packmol_step tests yapf --diff --recursive packmol_step tests - - name: Build documentation - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - shell: bash -l {0} - run: | - docs/buildDocs.sh test: name: Test ${{ matrix.os }} Py${{ matrix.python-version }} runs-on: ${{ matrix.os }} - needs: lint-docs + needs: lint strategy: matrix: os: [macOS-latest, ubuntu-latest] diff --git a/.github/workflows/Docs.yaml b/.github/workflows/Docs.yaml new file mode 100644 index 0000000..6929b4f --- /dev/null +++ b/.github/workflows/Docs.yaml @@ -0,0 +1,40 @@ +name: Documentation + +on: push + +jobs: + docs: + name: Docs ubuntu-latest Py3.8 + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v1 + with: + # This gets all branches (1 = only current branch) + fetch-depth: 0 + - name: Additional info about the build + shell: bash + run: | + uname -a + df -h + ulimit -a + # More info on options: https://github.com/conda-incubator/setup-miniconda + - uses: conda-incubator/setup-miniconda@v2 + with: + python-version: 3.8 + environment-file: devtools/conda-envs/test_env.yaml + activate-environment: test + auto-update-conda: false + auto-activate-base: false + show-channel-urls: true + - name: Install package + # conda setup requires this special shell + shell: bash -l {0} + run: | + python -m pip install . --no-deps + conda list + - name: Build documentation + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + shell: bash -l {0} + run: | + docs/buildDocs.sh diff --git a/.github/workflows/Release.yaml b/.github/workflows/Release.yaml index 186af73..e9566d2 100644 --- a/.github/workflows/Release.yaml +++ b/.github/workflows/Release.yaml @@ -1,18 +1,14 @@ name: Release on: - # GitHub has started calling new repo's first branch "main" https://github.com/github/renaming - # Existing codes likely still have "master" as the primary branch - # Both are tracked here to keep legacy and new codes working release: types: [published] branches: - - "master" - "main" jobs: - lint-docs: - name: Lint-Docs ubuntu-latest Py3.8 + lint: + name: Lint ubuntu-latest Py3.8 runs-on: ubuntu-latest steps: - uses: actions/checkout@v1 @@ -45,17 +41,11 @@ jobs: run: | flake8 packmol_step tests yapf --diff --recursive packmol_step tests - - name: Build documentation - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - shell: bash -l {0} - run: | - docs/buildDocs.sh test: name: Test ${{ matrix.os }} Py${{ matrix.python-version }} runs-on: ${{ matrix.os }} - needs: lint-docs + needs: lint strategy: matrix: os: [macOS-latest, ubuntu-latest] @@ -98,7 +88,7 @@ jobs: # only to test.pypi, otherwise to both it and the main pypi. if: github.event_name == 'release' && startsWith(github.ref, 'refs/tags') runs-on: ubuntu-latest - needs: [lint-docs, test] + needs: [lint, test] steps: - uses: actions/checkout@v1 - name: Set up Python 3.8 diff --git a/README.rst b/README.rst index bef2101..e5ad9e0 100644 --- a/README.rst +++ b/README.rst @@ -2,8 +2,12 @@ packmol step ============ -.. image:: https://img.shields.io/travis/molssi-seamm/packmol_step.svg - :target: https://travis-ci.org/molssi-seamm/packmol_step +.. image:: https://img.shields.io/github/issues-pr-raw/molssi-seamm/packmol_step + :target: https://github.com/molssi-seamm/packmol_step/pulls + :alt: GitHub pull requests + +.. image:: https://github.com/molssi-seamm/packmol_step/workflows/CI/badge.svg + :target: https://github.com/molssi-seamm/packmol_step/actions :alt: Build Status .. image:: https://codecov.io/gh/molssi-seamm/packmol_step/branch/master/graph/badge.svg @@ -14,8 +18,8 @@ packmol step :target: https://lgtm.com/projects/g/molssi-seamm/packmol_step/context:python :alt: Code Quality -.. image:: https://readthedocs.org/projects/packmol-step/badge/?version=latest - :target: https://packmol-step.readthedocs.io/en/latest/?badge=latest +.. image:: https://github.com/molssi-seamm/packmol_step/workflows/Documentation/badge.svg + :target: https://molssi-seamm.github.io/packmol_step/index.html :alt: Documentation Status .. image:: https://pyup.io/repos/github/molssi-seamm/packmol_step/shield.svg @@ -30,7 +34,7 @@ A step for a SEAMM flowchart for building periodic fluid boxes using Packmol * Free software: BSD license -* Documentation: https://packmol-step.readthedocs.io. +* Documentation: https://molssi-seamm.github.io/packmol_step/index.html Features diff --git a/packmol_step/packmol.py b/packmol_step/packmol.py index 591eb57..91a9cf7 100644 --- a/packmol_step/packmol.py +++ b/packmol_step/packmol.py @@ -134,8 +134,8 @@ def run(self): next_node = super().run(printer) # Get the system - systems = self.get_variable('_systems') - system = self.get_variable('_system') + system_db = self.get_variable('_system_db') + configuration = system_db.system.configuration # The options from command line, config file ... path = self.options['packmol_path'] @@ -193,7 +193,7 @@ def run(self): ) tmp = self.calculate( - system, + configuration, size=size, volume=volume, density=density, @@ -217,7 +217,7 @@ def run(self): lines.append('end structure') lines.append('') - files = {'input.pdb': system.to_pdb_text()} + files = {'input.pdb': configuration.to_pdb_text()} files['input.inp'] = '\n'.join(lines) self.logger.log(0, pprint.pformat(files)) @@ -239,15 +239,17 @@ def run(self): # need to graft to the original structure. # Create a new, temporary system and get the coordinates - tmp_sys = systems.create_system('tmp_sys', temporary=True) - tmp_sys.from_pdb_text(result['packmol.pdb']['data']) - n_atoms = tmp_sys.n_atoms() - xs = [*tmp_sys.atoms['x']] - ys = [*tmp_sys.atoms['y']] - zs = [*tmp_sys.atoms['z']] - del systems['tmp_sys'] - - n_atoms_per_molecule = system.n_atoms() + tmp_sys = system_db.create_system('tmp_sys', make_current=False) + tmp_configuration = tmp_sys.create_configuration('tmp') + tmp_configuration.from_pdb_text(result['packmol.pdb']['data']) + tmp_atoms = tmp_configuration.atoms + n_atoms = tmp_atoms.n_atoms + xs = [*tmp_atoms['x']] + ys = [*tmp_atoms['y']] + zs = [*tmp_atoms['z']] + system_db.delete_system(tmp_sys) + + n_atoms_per_molecule = configuration.n_atoms if n_atoms_per_molecule * n_molecules != n_atoms: raise RuntimeError( 'Serious problem in Packmol with the number of atoms' @@ -256,47 +258,35 @@ def run(self): ) ) - # get the initial atoms so that we can duplicate them - rows = system.atoms.atoms() - atom_data = {} - columns = [x[0] for x in rows.description] - for column in columns: - atom_data[column] = [] - for row in rows: - for column, value in zip(columns, row): - atom_data[column].append(value) - atom_ids = atom_data['id'] + # Get a copy of the current atom and bond data + atoms = configuration.atoms + atom_data = atoms.get_as_dict() + # index of atoms to use for bonds + index = {j: i for i, j in enumerate(atom_data['id'])} del atom_data['id'] - to_index = {j: i for i, j in enumerate(atom_ids)} - - # and bonds - rows = system.bonds.bonds() - bond_data = {} - columns = [x[0] for x in rows.description] - for column in columns: - bond_data[column] = [] - for row in rows: - for column, value in zip(columns, row): - bond_data[column].append(value) - i_index = [to_index[i] for i in bond_data['i']] - j_index = [to_index[j] for j in bond_data['j']] + bonds = configuration.bonds + bond_data = bonds.get_as_dict() + del bond_data['id'] + + i_index = [index[i] for i in bond_data['i']] + j_index = [index[j] for j in bond_data['j']] # Append the atoms and bonds n_molecules-1 times to give n_molecules for copy in range(1, n_molecules): - new_atoms = system.atoms.append(**atom_data) + new_atoms = configuration.atoms.append(**atom_data) bond_data['i'] = [new_atoms[i] for i in i_index] bond_data['j'] = [new_atoms[j] for j in j_index] - system.bonds.append(**bond_data) + configuration.bonds.append(**bond_data) # And set the coordinates to the correct ones - system.atoms['x'] = xs - system.atoms['y'] = ys - system.atoms['z'] = zs + configuration.atoms['x'] = xs + configuration.atoms['y'] = ys + configuration.atoms['z'] = zs # make periodic of correct size - system.periodicity = 3 - system.cell.set_cell(size, size, size, 90.0, 90.0, 90.0) + configuration.periodicity = 3 + configuration.cell.parameters = (size, size, size, 90.0, 90.0, 90.0) string = 'Created a cubic cell {size:.5~P} on a side' string += ' with {n_molecules} molecules' @@ -326,7 +316,7 @@ def run(self): def calculate( self, - system, + configuration, size=None, volume=None, density=None, @@ -337,13 +327,13 @@ def calculate( ): """Work out the other variables given any two independent ones""" - if system.n_atoms() == 0: + if configuration.n_atoms == 0: self.logger.error('Packmol calculate: there is no structure!') raise RuntimeError('Packmol calculate: there is no structure!') - elements = system.atoms.symbols() + elements = configuration.atoms.symbols n_atoms_per_molecule = len(elements) - molecular_mass = system.mass() * ureg.g / ureg.mol # g/mol + molecular_mass = configuration.mass * ureg.g / ureg.mol # g/mol molecular_mass.ito('kg') n_parameters = 0 diff --git a/requirements.txt b/requirements.txt index 4cd9794..f2a6725 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1 +1 @@ -seamm==2020.12.4 +seamm==2021.2.2 diff --git a/tests/conftest.py b/tests/conftest.py index 5d39d7d..53a8327 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -5,7 +5,7 @@ import pytest -from molsystem.systems import Systems +from molsystem import SystemDB def pytest_addoption(parser): @@ -32,20 +32,45 @@ def pytest_collection_modifyitems(config, items): @pytest.fixture() -def system(): - systems = Systems() - system = systems.create_system('seamm', temporary=True) +def empty_db(): + """Create a system db with no systems.""" + db = SystemDB(filename='file:seamm_db?mode=memory&cache=shared') - yield system + yield db - del systems['seamm'] + db.close() + try: + del db + except: # noqa: E722 + print('Caught error deleting the database') @pytest.fixture() -def Argon(system): +def db(empty_db): + """Create an empty system db.""" + system = empty_db.create_system(name='default') + system.create_configuration(name='default') + + return empty_db + + +@pytest.fixture() +def system(db): + """An empty system.""" + return db.system + + +@pytest.fixture() +def configuration(system): + """An empty system.""" + return system.configuration + + +@pytest.fixture() +def Argon(configuration): """An system object for an argon atom """ - system.name = 'argon' - system['atoms'].append(x=0.0, y=0.0, z=0.0, symbol=['Ar']) + configuration.name = 'argon' + configuration.atoms.append(x=0.0, y=0.0, z=0.0, symbol=['Ar']) - return system + return configuration diff --git a/tests/test_calculate.py b/tests/test_calculate.py index 429624f..308e745 100644 --- a/tests/test_calculate.py +++ b/tests/test_calculate.py @@ -124,13 +124,13 @@ def test_density_mass(instance, Argon): # Resets the system! Needs to be at end -def test_no_system(instance, system): +def test_no_system(instance, configuration): """Test calculation of cell. First error with empty system.""" with pytest.raises( RuntimeError, match=r"Packmol calculate: there is no structure!" ): instance.calculate( - system, + configuration, size=Q_(10, 'Å'), n_molecules=100 )