From 5878963ea21f86d2100c16fe10d7850fedfe5471 Mon Sep 17 00:00:00 2001 From: Lauri Himanen Date: Tue, 20 Aug 2024 16:23:32 +0300 Subject: [PATCH] Refactored project setup, added tests to CI, updated Cython. --- .github/workflows/test.yml | 32 +++++++++++++++++++ README.md | 2 +- pyproject.toml | 40 +++++++++++++++++++++++ scripts/setup.sh | 3 ++ scripts/test.sh | 3 ++ setup.py | 36 ++------------------- src/pyzeo/extension.cpp | 20 ++++-------- tests/test_areavol.py | 61 +++++++++++++++++------------------ tests/test_cluster.py | 25 ++++++++------- tests/test_cycle.py | 47 ++++++++++++++------------- tests/test_highaccuracy.py | 65 +++++++++++++++++++------------------- tests/test_netstorage.py | 18 +++++------ tests/test_psd.py | 3 +- 13 files changed, 200 insertions(+), 155 deletions(-) create mode 100644 .github/workflows/test.yml create mode 100644 pyproject.toml create mode 100755 scripts/setup.sh create mode 100755 scripts/test.sh diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 0000000..9955a84 --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,32 @@ +# This workflow will install Python dependencies, run tests and lint with a +# variety of Python versions For more information see: +# https://help.github.com/actions/language-and-framework-guides/using-python-with-github-actions + +name: test + +on: + push: + branches: [ "main"] + pull_request: + branches: [ "main"] + +jobs: + build: + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + python-version: ["3.8", "3.9", "3.10", "3.11", "3.12"] + + steps: + - uses: actions/checkout@v4 + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v5 + with: + python-version: ${{ matrix.python-version }} + - name: Install dependencies + run: | + cd ${GITHUB_WORKSPACE}/scripts && ./setup.sh + - name: Run unit tests + run: | + cd ${GITHUB_WORKSPACE}/scripts && ./test.sh \ No newline at end of file diff --git a/README.md b/README.md index 78630bd..abe9ae2 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ Python wrapper for the [Zeo++ library](http://zeoplusplus.org). Based on the lat ## Installation -We provide pre-built wheels for most platforms (including Apple Silicon). So in most cases you will want to install the package with `pip`: +We provide pre-built wheels for several platforms (including Apple Silicon). So in most cases you will want to install the package with `pip`: ```sh pip install pyzeo diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..7327f86 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,40 @@ +[build-system] +requires = ["setuptools", "wheel"] +build-backend = "setuptools.build_meta" + +[project] +name = 'pyzeo' +version = '0.1.6' +description = 'Python interface to Zeo++' +readme = "README.md" +authors = [{ name = "Lauri Himanen" }] +license = { file = "LICENSE" } +requires-python = ">=3.8" +dependencies = [] +classifiers = [ + "Development Status :: 3 - Alpha", + "Programming Language :: C++", + "Programming Language :: Cython", + "Programming Language :: Python", + "Programming Language :: Python :: 3", + "Programming Language :: Python :: 3.8", + "Programming Language :: Python :: 3.9", + "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: 3.12", + "Programming Language :: Python :: 3 :: Only", + "Intended Audience :: Science/Research", + "Topic :: Scientific/Engineering" +] +keywords = ['zeo++', 'porous', 'materials', 'science'] + +[project.urls] +Source = "https://github.com/nomad-coe/pyzeo" + +[project.optional-dependencies] +dev = [ + "pytest", +] + +[tool.setuptools.package-dir] +"" = "src" \ No newline at end of file diff --git a/scripts/setup.sh b/scripts/setup.sh new file mode 100755 index 0000000..19eadad --- /dev/null +++ b/scripts/setup.sh @@ -0,0 +1,3 @@ +cd .. +python -m pip install --upgrade pip +pip install .[dev] diff --git a/scripts/test.sh b/scripts/test.sh new file mode 100755 index 0000000..9f564e4 --- /dev/null +++ b/scripts/test.sh @@ -0,0 +1,3 @@ +#!/usr/bin/env bash +cd ../tests +pytest diff --git a/setup.py b/setup.py index b42aebf..8c55519 100755 --- a/setup.py +++ b/setup.py @@ -2,7 +2,7 @@ import platform from distutils.ccompiler import new_compiler from distutils.sysconfig import customize_compiler -from setuptools import setup, find_packages +from setuptools import setup from setuptools.extension import Extension from subprocess import getoutput @@ -89,35 +89,5 @@ def using_clang(): from Cython.Build import cythonize extensions = cythonize(extensions) -setup( - name='pyzeo', - version='0.1.5', - description="Python interface to Zeo++", - long_description="Python interface to Zeo++", - url="https://github.com/nomad-coe/pyzeo", - author="Lauri Himanen", - license="", - classifiers=[ - "Development Status :: 3 - Alpha", - "Programming Language :: C++", - "Programming Language :: Cython", - "Programming Language :: Python", - "Programming Language :: Python :: 3", - "Programming Language :: Python :: 3.8", - "Programming Language :: Python :: 3.9", - "Programming Language :: Python :: 3.10", - "Programming Language :: Python :: 3.11", - "Programming Language :: Python :: 3.12", - "Programming Language :: Python :: 3 :: Only", - "Intended Audience :: Science/Research", - "Topic :: Scientific/Engineering" - ], - # In the Cython build guide it is said that zip_safe should be disabled - # when building with setuptools - packages=find_packages('src'), - package_dir={'': 'src'}, - zip_safe=False, - ext_modules=extensions, - keywords="zeo++ porous materials science", - python_requires=">=3.8", -) +if __name__ == "__main__": + setup(ext_modules=extensions) \ No newline at end of file diff --git a/src/pyzeo/extension.cpp b/src/pyzeo/extension.cpp index 15b8438..5a1d3eb 100644 --- a/src/pyzeo/extension.cpp +++ b/src/pyzeo/extension.cpp @@ -25,13 +25,7 @@ "-Wall", "-ansi", "-pedantic", - "-O3", - "-stdlib=libc++", - "-mmacosx-version-min=10.9" - ], - "extra_link_args": [ - "-stdlib=libc++", - "-mmacosx-version-min=10.7" + "-O3" ], "include_dirs": [ "src/pyzeo" @@ -17314,7 +17308,7 @@ static PyObject *__pyx_pf_5pyzeo_9extension_11AtomNetwork_30perform_voronoi_deco PyObject *__pyx_v_edge_centers = NULL; std::vector __pyx_v_vedges; std::vector __pyx_v_vnodes; - std::vector ::size_type __pyx_v_i; + std::vector ::size_type __pyx_v_i; int __pyx_v_edge_orig; int __pyx_v_edge_end; VOR_NODE __pyx_v_o_vnode; @@ -17344,7 +17338,7 @@ static PyObject *__pyx_pf_5pyzeo_9extension_11AtomNetwork_30perform_voronoi_deco std::vector __pyx_t_5; std::vector ::size_type __pyx_t_6; std::vector ::size_type __pyx_t_7; - std::vector ::size_type __pyx_t_8; + std::vector ::size_type __pyx_t_8; int __pyx_t_9; PyObject *__pyx_t_10 = NULL; PyObject *__pyx_t_11 = NULL; @@ -17629,10 +17623,10 @@ static PyObject *__pyx_pf_5pyzeo_9extension_11AtomNetwork_30perform_voronoi_deco * vfaces = vcells[i].faces * for j in range(vfaces.size()): */ - __pyx_t_8 = __pyx_v_vcells.size(); - __pyx_t_14 = __pyx_t_8; - for (__pyx_t_15 = 0; __pyx_t_15 < __pyx_t_14; __pyx_t_15+=1) { - __pyx_v_i = __pyx_t_15; + __pyx_t_14 = __pyx_v_vcells.size(); + __pyx_t_15 = __pyx_t_14; + for (__pyx_t_6 = 0; __pyx_t_6 < __pyx_t_15; __pyx_t_6+=1) { + __pyx_v_i = __pyx_t_6; /* "pyzeo/extension.pyx":705 * face_node_ids = set() diff --git a/tests/test_areavol.py b/tests/test_areavol.py index d27ea81..7f263bc 100644 --- a/tests/test_areavol.py +++ b/tests/test_areavol.py @@ -1,32 +1,33 @@ -from pyzeo.netstorage import AtomNetwork -from pyzeo.area_volume import volume, surface_area +def test_areavol(): + from pyzeo.netstorage import AtomNetwork + from pyzeo.area_volume import volume, surface_area -atmnet = AtomNetwork.read_from_CSSR("MgO_vac1.cssr", rad_file="MgO.rad") -vol_str = volume(atmnet, 0.1, 0.05, 20000) -lines = vol_str.decode("utf-8").split('\n') -for line in lines: - if "Number_of_pockets" in line: - print('---------') - print(line) - print('---------') -vol_str, ha_atmnet = volume(atmnet, 0.1, 0.05, 7000, True) -lines = vol_str.decode("utf-8").split('\n') -for line in lines: - if "Number_of_pockets" in line: - print('---------') - print(line) - print('---------') -#print("--------") -#print(vol_str) -#print("--------") -sa_str = surface_area(atmnet, 0.1, 0.05, 7000, False) -lines = sa_str.decode("utf-8").split('\n') -for line in lines: - if "Number_of_pockets" in line: - print('---------') - print(line.split()) - print('---------') -#print("--------") -#print(sa_str) -#print("--------") + atmnet = AtomNetwork.read_from_CSSR("MgO_vac1.cssr", rad_file="MgO.rad") + vol_str = volume(atmnet, 0.1, 0.05, 20000) + lines = vol_str.decode("utf-8").split('\n') + for line in lines: + if "Number_of_pockets" in line: + print('---------') + print(line) + print('---------') + vol_str, ha_atmnet = volume(atmnet, 0.1, 0.05, 7000, True) + lines = vol_str.decode("utf-8").split('\n') + for line in lines: + if "Number_of_pockets" in line: + print('---------') + print(line) + print('---------') + #print("--------") + #print(vol_str) + #print("--------") + sa_str = surface_area(atmnet, 0.1, 0.05, 7000, False) + lines = sa_str.decode("utf-8").split('\n') + for line in lines: + if "Number_of_pockets" in line: + print('---------') + print(line.split()) + print('---------') + #print("--------") + #print(sa_str) + #print("--------") diff --git a/tests/test_cluster.py b/tests/test_cluster.py index 15529a0..631c012 100644 --- a/tests/test_cluster.py +++ b/tests/test_cluster.py @@ -1,17 +1,18 @@ -from pyzeo.netstorage import AtomNetwork -from pyzeo.cluster import pruned_highaccuracy_voronoi_network, \ - get_nearest_largest_diameter_highaccuracy_vornode +def test_cluster(): + from pyzeo.netstorage import AtomNetwork + from pyzeo.cluster import pruned_highaccuracy_voronoi_network, \ + get_nearest_largest_diameter_highaccuracy_vornode -atmnet = AtomNetwork.read_from_CSSR("MgO.cssr", rad_file="MgO.rad") -vornet,ecs,fcs = atmnet.perform_voronoi_decomposition() -vornet.analyze_writeto_XYZ('mgo_low', 0.4, atmnet) + atmnet = AtomNetwork.read_from_CSSR("MgO.cssr", rad_file="MgO.rad") + vornet, ecs, fcs = atmnet.perform_voronoi_decomposition() + vornet.analyze_writeto_XYZ('mgo_low', 0.4, atmnet) -# Pruned high accuracy voronoi network -ha_vornet = pruned_highaccuracy_voronoi_network(atmnet, 0.7) -ha_vornet.analyze_writeto_XYZ('mgo_high_prune', 0.4, atmnet) + # Pruned high accuracy voronoi network + ha_vornet = pruned_highaccuracy_voronoi_network(atmnet, 0.7) + ha_vornet.analyze_writeto_XYZ('mgo_high_prune', 0.4, atmnet) -# Reduced high accuracy voronoi network -ha_red_vornet = get_nearest_largest_diameter_highaccuracy_vornode(atmnet) -ha_red_vornet.analyze_writeto_XYZ('mgo_high_red', 0.4, atmnet) + # Reduced high accuracy voronoi network + ha_red_vornet = get_nearest_largest_diameter_highaccuracy_vornode(atmnet) + ha_red_vornet.analyze_writeto_XYZ('mgo_high_red', 0.4, atmnet) diff --git a/tests/test_cycle.py b/tests/test_cycle.py index ed7580a..6017c4d 100644 --- a/tests/test_cycle.py +++ b/tests/test_cycle.py @@ -1,29 +1,28 @@ -import sys -from pyzeo.netstorage import AtomNetwork -from pyzeo.cycle import compute_centroid_4cycles, compute_face_centers +def test_cycle(): + from pyzeo.netstorage import AtomNetwork + from pyzeo.cycle import compute_centroid_4cycles, compute_face_centers -atmnet = AtomNetwork.read_from_CSSR("MgO.cssr", rad_file="MgO.rad") -compute_face_centers(atmnet) -sys.exit() + atmnet = AtomNetwork.read_from_CSSR("MgO.cssr", rad_file="MgO.rad") + compute_face_centers(atmnet) -vornet = atmnet.perform_voronoi_decomposition() -oh_interstitials = compute_centroid_4cycles(vornet) + vornet, _, _ = atmnet.perform_voronoi_decomposition() + oh_interstitials = compute_centroid_4cycles(vornet) -ids_set = set() -i = 0 -while i < len(oh_interstitials): - node_ids = frozenset(oh_interstitials[i]['ids']) - if node_ids not in ids_set: - ids_set.add(node_ids) - i = i+1 - else: - oh_interstitials.pop(i) - -print(len(oh_interstitials)) -for inter in oh_interstitials: - node_ids = inter['ids'] - print(node_ids) - coord = inter['coords'] - print(coord.x, coord.y, coord.z) + ids_set = set() + i = 0 + while i < len(oh_interstitials): + node_ids = frozenset(oh_interstitials[i]['ids']) + if node_ids not in ids_set: + ids_set.add(node_ids) + i = i+1 + else: + oh_interstitials.pop(i) + + print(len(oh_interstitials)) + for inter in oh_interstitials: + node_ids = inter['ids'] + print(node_ids) + coord = inter['coords'] + print(coord.x, coord.y, coord.z) diff --git a/tests/test_highaccuracy.py b/tests/test_highaccuracy.py index a5237af..ce57903 100644 --- a/tests/test_highaccuracy.py +++ b/tests/test_highaccuracy.py @@ -1,33 +1,34 @@ -from pyzeo.high_accuracy import high_accuracy_atomnet -from pyzeo.netstorage import AtomNetwork +def test_highaccuracy(): + from pyzeo.high_accuracy import high_accuracy_atomnet + from pyzeo.netstorage import AtomNetwork -atmnet = AtomNetwork.read_from_CSSR("MgO.cssr", rad_file="MgO.rad") -atmnet.write_to_XYZ("orig_mgo.xyz", False, True) -vornet,ecs,fcs = atmnet.perform_voronoi_decomposition() -vornet.write_to_XYZ("orig_mgo_voro.xyz", 0) -vornet.analyze_writeto_XYZ('orig_mgo', 0.4, atmnet) -high_accuracy_atomnet(atmnet, "DEF") -vornet,ecs,fcs = atmnet.perform_voronoi_decomposition() -vornet.write_to_XYZ("test_high.xyz", 0) -vornet.analyze_writeto_XYZ('mgo_high', 0.4, atmnet) -atmnet.write_to_CIF("highacc_MgO.cif") -atmnet.calculate_free_sphere_parameters('MgO.res') -# -#atmnet = AtomNetwork.read_from_CIF("mgo.cif", rad_file="MgO.rad") -#vornet = atmnet.perform_voronoi_decomposition() -#vornet.write_to_XYZ("mgo.xyz", 0) -#vornet.analyze_writeto_XYZ('mgo1', 0.4, atmnet) -#high_accuracy_atmnet(atmnet, "DEF") -#vornet = atmnet.perform_voronoi_decomposition() -#vornet.write_to_XYZ("mgo_high.xyz", 0) -#vornet.analyze_writeto_XYZ('mgo_high', 0.4, atmnet) -#atmnet.write_to_CIF("highacc_mgo.cif") -#atmnet.calculate_free_sphere_parameters('mgo.res') -# -# -#atmnet = AtomNetwork.read_from_CIF("mgo.cif", rad_file="MgO.rad") -#high_accuracy_atmnet(atmnet, "LOW") -#atmnet.write_to_XYZ("mgo_ha_lowset.xyz", False, True) -#vornet = atmnet.perform_voronoi_decomposition() -#vornet.write_to_XYZ("mgo_ha_low.xyz", 0) -#vornet.analyze_writeto_XYZ('mgo_ha_low', 0.4, atmnet) + atmnet = AtomNetwork.read_from_CSSR("MgO.cssr", rad_file="MgO.rad") + atmnet.write_to_XYZ("orig_mgo.xyz", False, True) + vornet,ecs,fcs = atmnet.perform_voronoi_decomposition() + vornet.write_to_XYZ("orig_mgo_voro.xyz", 0) + vornet.analyze_writeto_XYZ('orig_mgo', 0.4, atmnet) + high_accuracy_atomnet(atmnet, "DEF") + vornet,ecs,fcs = atmnet.perform_voronoi_decomposition() + vornet.write_to_XYZ("test_high.xyz", 0) + vornet.analyze_writeto_XYZ('mgo_high', 0.4, atmnet) + atmnet.write_to_CIF("highacc_MgO.cif") + atmnet.calculate_free_sphere_parameters('MgO.res') + # + #atmnet = AtomNetwork.read_from_CIF("mgo.cif", rad_file="MgO.rad") + #vornet = atmnet.perform_voronoi_decomposition() + #vornet.write_to_XYZ("mgo.xyz", 0) + #vornet.analyze_writeto_XYZ('mgo1', 0.4, atmnet) + #high_accuracy_atmnet(atmnet, "DEF") + #vornet = atmnet.perform_voronoi_decomposition() + #vornet.write_to_XYZ("mgo_high.xyz", 0) + #vornet.analyze_writeto_XYZ('mgo_high', 0.4, atmnet) + #atmnet.write_to_CIF("highacc_mgo.cif") + #atmnet.calculate_free_sphere_parameters('mgo.res') + # + # + #atmnet = AtomNetwork.read_from_CIF("mgo.cif", rad_file="MgO.rad") + #high_accuracy_atmnet(atmnet, "LOW") + #atmnet.write_to_XYZ("mgo_ha_lowset.xyz", False, True) + #vornet = atmnet.perform_voronoi_decomposition() + #vornet.write_to_XYZ("mgo_ha_low.xyz", 0) + #vornet.analyze_writeto_XYZ('mgo_ha_low', 0.4, atmnet) diff --git a/tests/test_netstorage.py b/tests/test_netstorage.py index 2a1860d..7dcf730 100644 --- a/tests/test_netstorage.py +++ b/tests/test_netstorage.py @@ -1,10 +1,10 @@ -from pyzeo.netstorage import AtomNetwork +def test_netstorage(): + from pyzeo.netstorage import AtomNetwork -atmnet = AtomNetwork.read_from_CSSR("MgO.cssr", rad_file="MgO.rad") -a = atmnet.perform_voronoi_decomposition() -#vornet,edge_centers, face_centers = atmnet.perform_voronoi_decomposition() -#print 'edge_centers', edge_centers -#print 'face_centers', face_centers -print(len(a)) - -print(a) + atmnet = AtomNetwork.read_from_CSSR("MgO.cssr", rad_file="MgO.rad") + a = atmnet.perform_voronoi_decomposition() + #vornet,edge_centers, face_centers = atmnet.perform_voronoi_decomposition() + #print 'edge_centers', edge_centers + #print 'face_centers', face_centers + print(len(a)) + print(a) diff --git a/tests/test_psd.py b/tests/test_psd.py index 1d935c7..e7ea9a6 100644 --- a/tests/test_psd.py +++ b/tests/test_psd.py @@ -1 +1,2 @@ -from pyzeo.psd import calc_pore_size_distribution +def test_psd(): + from pyzeo.psd import calc_pore_size_distribution