diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml new file mode 100644 index 00000000..1d649241 --- /dev/null +++ b/.github/workflows/main.yml @@ -0,0 +1,93 @@ +name: main + + +# Automatically cancel a previous run. +concurrency: + group: ${{ github.head_ref || github.run_id }} + cancel-in-progress: true + + +on: + push: + branches: + - master + pull_request: + branches: + - master + release: + types: [published] + +jobs: + + build_sdist: + name: Build SDist + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + + - name: Build SDist + run: pipx run build --sdist + + - name: Check metadata + run: pipx run twine check dist/* + + - uses: actions/upload-artifact@v3 + with: + path: dist/*.tar.gz + + build_wheel: + name: Build wheel on ${{ matrix.os }} + runs-on: ${{ matrix.os }} + strategy: + matrix: + os: ['ubuntu-latest', 'macos-latest'] + steps: + - uses: actions/checkout@v3 + + - name: Build wheels + uses: pypa/cibuildwheel@v2.12.0 + env: + CIBW_ARCHS_MACOS: x86_64 arm64 + + - uses: actions/upload-artifact@v3 + with: + path: wheelhouse/*.whl + + + upload_test: + name: Upload if test release + needs: [build_sdist, build_wheel] + runs-on: ubuntu-latest + if: github.event_name == 'push' && github.ref == 'refs/heads/test_release' + steps: + - uses: actions/setup-python@v4 + with: + python-version: "3.10" + + - uses: actions/download-artifact@v3 + with: + name: artifact + path: dist + + - uses: pypa/gh-action-pypi-publish@v1.6.4 + with: + name: __token__ + password: ${{ secrets.PYPI_API_TOKEN }} + repository_url: https://test.pypi.org/legacy/ + + upload: + name: Upload if new release + needs: [build_sdist, build_wheel] + runs-on: ubuntu-latest + if: github.event_name == 'release' && github.event.action == 'published' + + steps: + - uses: actions/download-artifact@v3 + with: + name: artifact + path: dist + + - uses: pypa/gh-action-pypi-publish@v1.5.0 + with: + user: __token__ + password: ${{ secrets.pypi_password }} \ No newline at end of file diff --git a/MANIFEST.in b/MANIFEST.in new file mode 100644 index 00000000..f1b25d6a --- /dev/null +++ b/MANIFEST.in @@ -0,0 +1,9 @@ +include LICENSE.md +include README.md +include ompy/decomposition.pyx +include ompy/rebin.pyx +include ompy/gauss_smoothing.pyx +include ompy/stats/stats.cpp +include ompy/stats/erfinv.hpp +include ompy/examples/Dy164_raw.m +include ompy/examples/Si28_raw_matrix_compressed.m \ No newline at end of file diff --git a/ompy/examples/Dy164_raw.m b/ompy/examples/Dy164_raw.m new file mode 100644 index 00000000..96daf5dc Binary files /dev/null and b/ompy/examples/Dy164_raw.m differ diff --git a/ompy/examples/Si28_raw_matrix_compressed.m b/ompy/examples/Si28_raw_matrix_compressed.m new file mode 100644 index 00000000..ecc28044 Binary files /dev/null and b/ompy/examples/Si28_raw_matrix_compressed.m differ diff --git a/ompy/examples.py b/ompy/examples/__init__.py similarity index 88% rename from ompy/examples.py rename to ompy/examples/__init__.py index c699732d..5421765e 100644 --- a/ompy/examples.py +++ b/ompy/examples/__init__.py @@ -1,12 +1,13 @@ import os from typing import Tuple, List -from .matrix import Matrix +from ..matrix import Matrix import numpy as np -EXAMPLES = {'dy164': {'raw': "../../example_data/Dy164_raw.m", + +EXAMPLES = {'dy164': {'raw': "../Dy164_raw.m", # 'response': "../../data/Dy164_response_matrix.m" }, - 'si28': {'raw': "../../example_data/Si28_raw_matrix_compressed.m"} + 'si28': {'raw': "../Si28_raw_matrix_compressed.m"} } DATAPATH = os.path.abspath(__file__) diff --git a/ompy/spinfunctions.py b/ompy/spinfunctions.py index ad2c0b0d..66724fda 100644 --- a/ompy/spinfunctions.py +++ b/ompy/spinfunctions.py @@ -180,7 +180,7 @@ def gDisc_and_EB05(self, mass: int, NLDa: float, Eshift: float, Sn: float, sigma2_Sn = self.gEB05(mass, NLDa, Eshift, Ex=Sn) sigma2_EB05 = lambda Ex: self.gEB05(mass, NLDa, Eshift, Ex=Ex) # noqa x = [sigma2_disc[0], Sn] - y = [sigma2_disc[1], sigma2_EB05(Sn)] + y = [sigma2_disc[1], float(sigma2_EB05(Sn))] sigma2 = interp1d(x, y, bounds_error=False, fill_value=(sigma2_disc[1], sigma2_Sn)) diff --git a/src/erfinv.hpp b/ompy/stats/erfinv.hpp similarity index 100% rename from src/erfinv.hpp rename to ompy/stats/erfinv.hpp diff --git a/src/stats.cpp b/ompy/stats/stats.cpp similarity index 99% rename from src/stats.cpp rename to ompy/stats/stats.cpp index ab11f651..7a12c2d0 100644 --- a/src/stats.cpp +++ b/ompy/stats/stats.cpp @@ -1,11 +1,10 @@ #include #include -#include - #include "erfinv.hpp" + namespace py = pybind11; constexpr double sqrt2 = 1.41421356237309504880168872420969807856967187; diff --git a/pyproject.toml b/pyproject.toml index 95607b45..5ffbe521 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,8 +1,71 @@ [build-system] -requires = [ -"setuptools", -"numpy>=1.20.0", -"cython", -"pybind11>=2.6.0", -"wheel"] +requires = ["setuptools", "numpy>=1.20.0", "cython", "pybind11>=2.6.0", "wheel"] build-backend = "setuptools.build_meta" + +[project] +name = "OMpy" +version = "1.1.0" +authors = [ + {name="Jørgen Eriksson Midtbø", email="jorgenem@gmail.com"}, + {name="Fabio Zeiser", email="fabio.zeiser@fys.uio.no"}, + {name="Erlend Lima", email="erlenlim@fys.uio.no"} +] +maintainers = [ + {name="Erlend Lima", email="erlenlim@fys.uio.no"}, + {name="Vetle Wegner Ingeberg", email="vetlewi@fys.uio.no"} +] + +dependencies = [ +"cython", "numpy>=1.20.0", "pandas", "matplotlib", "termtables", +"pymultinest", "scipy", "uncertainties>=3.0.3", "tqdm", "pathos", "pybind11>=2.6.0"] + +description = "A python implementation of the Oslo method" +readme = "README.md" +requires-python = ">=3.8" +classifiers = [ + "License :: OSI Approved :: GNU General Public License v3 (GPLv3)", + "Programming Language :: Python :: 3", + "Programming Language :: Python :: 3 :: Only", + "Programming Language :: Python :: 3.8", + "Programming Language :: Python :: 3.9", + "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3.11", + "Intended Audience :: Science/Research", + "Topic :: Scientific/Engineering :: Physics", + ] + +[project.urls] +"Homepage" = "https://github.com/oslocyclotronlab/ompy" +"Bug Tracker" = "https://github.com/oslocyclotronlab/ompy/issues" + +[tool.cibuildwheel] +build = ["cp310-manylinux_x86_64", + "cp311-manylinux_x86_64", + "cp310-macosx_x86_64", + "cp311-macosx_x86_64", + "cp310-macosx_arm64", + "cp311-macosx_arm64"] + +skip = ["cp36-*", "cp37-*", "cp38-*", "cp39-*", "*-musllinux-*", "pp*"] +test-requires = "pytest" +test-command = "pytest {project}/tests" +test-skip = ["*-macosx_arm64, *-macosx_universal2:arm64", "*-*linux_{aarch64,ppc64le,s390x}"] + +[tool.cibuildwheel.macos] +before-all = [ + "git clone https://github.com/JohannesBuchner/MultiNest", + "cd MultiNest/build", + "cmake ..", + "make" +] +environment = {LD_LIBRARY_PATH="/home/runner/work/ompy/ompy/MultiNest/lib", MACOSX_DEPLOYMENT_TARGET="10.14", FC="/usr/local/bin/gfortran-11"} + +[tool.cibuildwheel.linux] +before-all = [ + "yum -y install blas-devel lapack-devel", + "git clone https://github.com/JohannesBuchner/MultiNest", + "cd MultiNest/build", + "cmake ..", + "make install" +] +environment = {LD_LIBRARY_PATH="/usr/local/lib"} diff --git a/release_note.md b/release_note.md index 7d1d42a7..b0263aec 100644 --- a/release_note.md +++ b/release_note.md @@ -12,6 +12,8 @@ Changed: - Fixed a bug where the `std` attribute of `Vector` was not saved to file. - Reimplemented PPF for normal distribution and truncated normal distribution in C++ for improved performance (about 300% faster than the SciPy implementation!). - Fixed a potential bug where `units` attribute is set erroniously when reading the discrete level density from file (`load_levels_discrete` and `load_levels_discrete_smooth`). +- Moved example data to the source folder such that they are distributed with the package and avalible regardless of if OMpy is installed with `-e` option or not. +- Source code for the `ompy.stats` sublibrary now lives in the `ompy` folder. Deprecated: - `shape` argument of Matrix for creation of a matrix filled with zeros. Use `ZerosMatrix` instead. diff --git a/setup.py b/setup.py index b409ae0a..895bf014 100755 --- a/setup.py +++ b/setup.py @@ -9,6 +9,11 @@ from ctypes.util import find_library from pybind11.setup_helpers import Pybind11Extension +try: + import wheel.bdist_wheel +except ImportError: + wheel = None + try: from Cython.Build import cythonize from Cython.Distutils import build_ext @@ -108,10 +113,15 @@ def write_version_py(filename='ompy/version_setup.py'): 'git_revision': GIT_REVISION}) finally: a.close() -write_version_py() +try: + write_version_py() +except: + pass # If macOS, use ctypes.util.find_library to determine if OpenMP is avalible. openmp = os.getenv("ompy_OpenMP") +if wheel is not None: # We do not build with OpenMP if wheel + openmp = False if openmp is None and platform.system() == 'Darwin': # Check if macOS if find_library("omp") != None: openmp = True @@ -131,7 +141,7 @@ def write_version_py(filename='ompy/version_setup.py'): if os.path.exists(fname): os.remove(fname) -extra_compile_args = ["-O3", "-ffast-math", "-march=native"] +extra_compile_args = ["-O3"] extra_link_args = [] if openmp and platform.system() == 'Darwin': extra_compile_args.insert(-1, "-Xpreprocessor -fopenmp") @@ -144,8 +154,8 @@ def write_version_py(filename='ompy/version_setup.py'): Extension("ompy.decomposition", ["ompy/decomposition.pyx"], # on MacOS the clang compiler pretends not to support OpenMP, but in fact it does so - extra_compile_args=extra_compile_args, - extra_link_args=extra_link_args, + #extra_compile_args=extra_compile_args, + #extra_link_args=extra_link_args, include_dirs=[numpy.get_include()] ), Extension("ompy.rebin", ["ompy/rebin.pyx"], include_dirs=[numpy.get_include()]), @@ -154,7 +164,7 @@ def write_version_py(filename='ompy/version_setup.py'): ext_modules_pybind11 = [ Pybind11Extension("ompy.stats", - ["src/stats.cpp"], + ["ompy/stats/stats.cpp"], cxx_std=20, extra_compile_args=["-O3"]), Pybind11Extension("ompy.rhosigchi", @@ -177,20 +187,42 @@ def write_version_py(filename='ompy/version_setup.py'): "pybind11>=2.6.0" ] -setup(name='OMpy', - version=get_version_info()[0], +def read_version(): + try: + with open("ompy/version_setup.py") as f: + ns = {} + exec(f.read(), ns) + version = ns["full_version"] + return version + except FileNotFoundError: + return VERSION + +try: + version = get_version_info()[0] +except: + version = read_version() + + +setup(name='ompy', + version=version, author="Jørgen Eriksson Midtbø, Fabio Zeiser, Erlend Lima", author_email=("jorgenem@gmail.com, " "fabio.zeiser@fys.uio.no, " "erlenlim@fys.uio.no"), url="https://github.com/oslocyclotronlab/ompy", - packages=find_packages(), + python_requires=">= 3.8", + packages=['ompy', 'ompy.examples', 'ompy.stats', 'ompy.introspection'], + package_data={ + "ompy": ["decomposition.pyx", "rebin.pyx", "gauss_smoothing.pyx"], + "ompy.stats": ['*.hpp'], + "ompy.examples": ['*.m'] + }, ext_modules=cythonize(ext_modules, compiler_directives={'language_level': "3", 'embedsignature': True}, compile_time_env={"OPENMP": openmp} )+ext_modules_pybind11, zip_safe=False, - install_requires=install_requires + setup_requires=["cython", "numpy>=1.20.0", "pybind11>=2.6.0"] )