diff --git a/.github/workflows/python-publish.yml b/.github/workflows/python-publish.yml new file mode 100644 index 00000000..460373b7 --- /dev/null +++ b/.github/workflows/python-publish.yml @@ -0,0 +1,101 @@ +# This workflow will upload a Python Package using Twine when a release is created +# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-python#publishing-to-package-registries + +# This workflow uses actions that are not certified by GitHub. +# They are provided by a third-party and are governed by +# separate terms of service, privacy policy, and support +# documentation. + +name: Upload Python Package + +on: + release: + types: [published] + push: + branches: + - "master" + +permissions: + contents: read + +jobs: + #build_wheels: + + #runs-on: ${{ matrix.os }} + + #strategy: + # matrix: + # os: [ubuntu-latest] + + #steps: + #- uses: actions/checkout@v4 + #- name: Set up Python + # uses: actions/setup-python@v5 + + #- name: Install dependencies + # run: | + # python -m pip install --upgrade pip + # python -m pip install cibuildwheel==2.20.0 + + #- name: Build wheels + # run: python -m cibuildwheel --output-dir dist + # env: + # CIBW_SKIP: cp36-* + # CIBW_BEFORE_BUILD_LINUX: yum install -y fftw-devel || apk add --upgrade fftw-dev || apt-get install libfftw3-dev + # CIBW_BEFORE_BUILD_MACOS: brew install fftw + + #- uses: actions/upload-artifact@v4 + # with: + # name: dist-${{ matrix.os }}-${{ strategy.job-index }} + # path: dist/*.whl + + build_sdist: + + runs-on: [ubuntu-latest] + + steps: + - uses: actions/checkout@v4 + - name: Set up Python + uses: actions/setup-python@v5 + + - name: Install FFTW3 on Linux + run: sudo apt-get install libfftw3-dev + + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install build + + - name: Build package + run: python -m build + + - name: Upload sdist + uses: actions/upload-artifact@v4 + with: + name: dist-sdist + path: dist/*.tar.gz + + publish-to-pypi: + name: Publish Python 🐍 distribution 📦 to PyPI + needs: + #- build_wheels + - build_sdist + runs-on: ubuntu-latest + if: github.event_name == 'release' && github.event.action == 'published' + + environment: + name: pypi + url: https://pypi.org/p/galario + + permissions: + id-token: write # IMPORTANT: mandatory for trusted publishing + + steps: + - name: Download all the dists + uses: actions/download-artifact@v4 + with: + path: dist + pattern: dist-* + merge-multiple: true + - name: Publish distribution 📦 to PyPI + uses: pypa/gh-action-pypi-publish@release/v1 diff --git a/.github/workflows/unit-tests.yml b/.github/workflows/unit-tests.yml index 14d0728e..b0262174 100644 --- a/.github/workflows/unit-tests.yml +++ b/.github/workflows/unit-tests.yml @@ -6,7 +6,11 @@ name: tests and docs # workflows running on Linux and MacOS have passwordless sudo rights: # https://stackoverflow.com/questions/57982945/how-to-apt-get-install-in-a-github-actions-workflow -on: push +on: + push: + branches: + - "master" + - "unit-tests_workflow_updates" jobs: test: @@ -18,7 +22,7 @@ jobs: shell: bash -l {0} strategy: matrix: - python-version: [ 3.6, 3.7, 3.8, 3.9 ] + python-version: [ 3.8, 3.9, '3.10', 3.11 ] env: OMP_NUM_THREADS: 2 steps: @@ -45,27 +49,23 @@ jobs: - name: Build and install galario, build docs run: | conda activate test - conda install astropy cython nomkl numpy pytest scipy sphinx + conda install astropy cython nomkl numpy pytest scipy sphinx scikit-build-core pip install coverage codecov pytest-cov - mkdir build && cd build - cmake -DCMAKE_INSTALL_PREFIX=/tmp -DCMAKE_PREFIX_PATH=${CONDA_PREFIX} .. - make - make install + pip install . - name: Run unit tests - run: python/py.test.sh -sv --cov=./ python/test_galario.py - working-directory: build + run: pytest -sv --cov=./ python/test_galario.py + #working-directory: build - name: Upload code coverage report run: bash <(curl -s https://codecov.io/bash) || echo 'Codecov failed to upload' - name: build docs run: | conda activate test pip install sphinx_py3doc_enhanced_theme sphinxcontrib-fulltoc - cd build - make docs + sphinx-build -M html docs docs/build - name: deploy docs if: github.ref == 'refs/heads/master' && matrix.python-version == '3.7' uses: JamesIves/github-pages-deploy-action@4.1.0 with: branch: gh-pages # The branch the action should deploy to. - folder: build/docs/html # The folder the action should deploy. + folder: docs/build/html # The folder the action should deploy. dry-run: false diff --git a/CMakeLists.txt b/CMakeLists.txt index d1a5c32e..e609b0d5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -99,12 +99,12 @@ else() message(STATUS "Skipping the ${PROJECT_NAME} python wrapper") endif() -find_package(Sphinx) -if(SPHINX_FOUND) - add_subdirectory(docs) -else() - message(STATUS "Cannot build the documentation without sphinx") -endif() +#find_package(Sphinx) +#if(SPHINX_FOUND) +# add_subdirectory(docs) +#else() +# message(STATUS "Cannot build the documentation without sphinx") +#endif() ### # uninstall target diff --git a/docs/CMakeLists.txt b/docs/CMakeLists.txt deleted file mode 100644 index 6eb38ade..00000000 --- a/docs/CMakeLists.txt +++ /dev/null @@ -1,57 +0,0 @@ -# https://eb2.co/blog/2012/03/sphinx-and-cmake-beautiful-documentation-for-c-projects/ - -if(NOT DEFINED SPHINX_THEME) - set(SPHINX_THEME default) -endif() - -if(NOT DEFINED SPHINX_THEME_DIR) - set(SPHINX_THEME_DIR) -endif() - -# configured documentation tools and intermediate build results -set(BINARY_BUILD_DIR "${CMAKE_CURRENT_BINARY_DIR}/_build") - -# Sphinx cache with pickled ReST documents -set(SPHINX_CACHE_DIR "${CMAKE_CURRENT_BINARY_DIR}/_doctrees") - -# HTML output directory -set(SPHINX_HTML_DIR "${CMAKE_CURRENT_BINARY_DIR}/html") - -configure_file( - "${CMAKE_CURRENT_SOURCE_DIR}/conf.py.in" - "${BINARY_BUILD_DIR}/conf.py" - @ONLY) - -# sphinx requires a _static directory, even if it's empty -file(MAKE_DIRECTORY "${BINARY_BUILD_DIR}/_static") - -# copy the _static/css directory with overridden css -file(MAKE_DIRECTORY "${BINARY_BUILD_DIR}/_static/css") -configure_file( - "${CMAKE_CURRENT_SOURCE_DIR}/_static/css/custom.css" - "${BINARY_BUILD_DIR}/_static/css/custom.css" - @ONLY) - -# copy the _templates directory with overridden templates -file(MAKE_DIRECTORY "${BINARY_BUILD_DIR}/_templates") -configure_file( - "${CMAKE_CURRENT_SOURCE_DIR}/_templates/layout.html" - "${BINARY_BUILD_DIR}/_templates/layout.html" - @ONLY) - -# github pages imposes jekyll theme by default. To avoid that, we need -# a `.nojekyll` file in the gh-pages branch file(WRITE -# "${SPHINX_HTML_DIR}/.nojekyll" "") - -add_custom_target(docs ALL - ${SPHINX_EXECUTABLE} - -q -b html - -c "${BINARY_BUILD_DIR}" - -d "${SPHINX_CACHE_DIR}" - "${CMAKE_CURRENT_SOURCE_DIR}" - "${SPHINX_HTML_DIR}" - COMMENT "Building HTML documentation with Sphinx") - -# sphinx can fail if it doesn't find the theme. This should not prevent building -# the actual source code, so docs have to be built explicitly -set_target_properties(docs PROPERTIES EXCLUDE_FROM_ALL TRUE) diff --git a/docs/conf.py.in b/docs/conf.py similarity index 99% rename from docs/conf.py.in rename to docs/conf.py index 26de1cdb..22c72d0e 100644 --- a/docs/conf.py.in +++ b/docs/conf.py @@ -72,7 +72,7 @@ # # This is also used if you do content translation via gettext catalogs. # Usually you set "language" from the command line for these cases. -language = None +language = 'en' # There are two options for replacing |today|: either, you set today to some # non-false value, then it is used: @@ -307,4 +307,4 @@ # override CSS file def setup(app): - app.add_stylesheet('css/custom.css') + app.add_css_file('css/custom.css') diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 00000000..21be900a --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,24 @@ +[build-system] +requires = [ + "scikit-build-core", + "numpy", + "Cython", + "pytest", +] +build-backend="scikit_build_core.build" + +[project] +name = "galario" +version = "1.2.2" +authors = [ + { name="Marco Tazzari", email="psheehan@nrao.edu" }, +] +description = "Gpu Accelerated Library for Analysing Radio Interferometer Observations" +readme = "README.md" + +[tool.scikit-build] +cmake.args = ['-DGALARIO_CHECK_CUDA=0'] + +[[tool.scikit-build.overrides]] +if.env.GALARIO_CHECK_CUDA = true +cmake.args = ['-DGALARIO_CHECK_CUDA=1'] diff --git a/python/CMakeLists.txt b/python/CMakeLists.txt index 6ba16729..026c1624 100644 --- a/python/CMakeLists.txt +++ b/python/CMakeLists.txt @@ -56,7 +56,7 @@ set(GALARIO_PYTHON_PKG_DIR "${PYTHON_PKG_DIR}" CACHE PATH "Current python instal # on unix: install .py and .so relative to ${CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT} install(DIRECTORY ${PYGALARIO_DIR} - DESTINATION "${GALARIO_PYTHON_PKG_DIR}" + DESTINATION ${SKBUILD_PLATLIB_DIR} FILES_MATCHING REGEX ".*py$|.*so$" ) diff --git a/python/libcommon.pyx b/python/libcommon.pyx index 54208888..353f9dd5 100644 --- a/python/libcommon.pyx +++ b/python/libcommon.pyx @@ -29,6 +29,9 @@ include "galario_config.pxi" cimport galario_defs as cpp +cdef extern from "numpy/arrayobject.h": + int PyArray_SetBaseObject(np.ndarray arr, PyObject* obj) + __all__ = ['arcsec', 'deg', 'cgs_to_Jy', 'pc', 'au', '_init', '_cleanup', 'set_v_origin', 'ngpus', 'use_gpu', 'threads', @@ -82,7 +85,8 @@ cdef class ArrayWrapper: # Create a 2D array, of length `nx*ny/2+1` ndarray = np.PyArray_SimpleNewFromData(2, shape, complex_typenum, self.data_ptr) - ndarray.base = self + #ndarray.base = self + PyArray_SetBaseObject(ndarray, self) # without this, data would be cleaned up right away Py_INCREF(self) diff --git a/python/utils.py b/python/utils.py index 8bf3742b..ceb1d14d 100644 --- a/python/utils.py +++ b/python/utils.py @@ -25,7 +25,7 @@ import numpy as np from scipy.interpolate import interp1d, RectBivariateSpline -from scipy.integrate import trapz, quadrature +from scipy.integrate import trapezoid, quadrature __all__ = ["py_sampleImage", "py_sampleProfile", "py_chi2Profile", "py_chi2Image", "radial_profile", "g_sweep_prototype", "sweep_ref", @@ -217,7 +217,7 @@ def g_sweep_prototype(I, Rmin, dR, nrow, ncol, dxy, inc, dtype_image='float64'): inc_cos = np.cos(inc) # radial extent in number of image pixels covered by the profile - rmax = min(np.int(np.ceil((Rmin+nrad*dR)/dxy)), irow_center) + rmax = min(int(np.ceil((Rmin+nrad*dR)/dxy)), irow_center) row_offset = irow_center-rmax col_offset = icol_center-rmax for irow in range(rmax*2): @@ -227,7 +227,7 @@ def g_sweep_prototype(I, Rmin, dR, nrow, ncol, dxy, inc, dtype_image='float64'): rr = np.sqrt((x/inc_cos)**2. + (y)**2.) # interpolate 1D - iR = np.int(np.floor((rr-Rmin) / dR)) + iR = int(np.floor((rr-Rmin) / dR)) if iR >= nrad-1: image[irow+row_offset, jcol+col_offset] = 0. else: @@ -394,10 +394,10 @@ def int_bilin_MT(f, x, y): for i in range(len(x)): t = y[i] - np.floor(y[i]) u = x[i] - np.floor(x[i]) - y0 = f[np.int(np.floor(y[i])), np.int(np.floor(x[i]))] - y1 = f[np.int(np.floor(y[i])) + 1, np.int(np.floor(x[i]))] - y2 = f[np.int(np.floor(y[i])) + 1, np.int(np.floor(x[i])) + 1] - y3 = f[np.int(np.floor(y[i])), np.int(np.floor(x[i])) + 1] + y0 = f[int(np.floor(y[i])), int(np.floor(x[i]))] + y1 = f[int(np.floor(y[i])) + 1, int(np.floor(x[i]))] + y2 = f[int(np.floor(y[i])) + 1, int(np.floor(x[i])) + 1] + y3 = f[int(np.floor(y[i])), int(np.floor(x[i])) + 1] vis_int[i] = t * u * (y0 - y1 + y2 - y3) vis_int[i] += t * (y1 - y0) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 5c16505b..2bbc7823 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -127,11 +127,11 @@ endif() # cuda # it would be nice if directory would let me access all libraries but there is no such property # https://cmake.org/cmake/help/v3.0/manual/cmake-properties.7.html install (TARGETS ${install_libs} - ARCHIVE DESTINATION lib - LIBRARY DESTINATION lib - RUNTIME DESTINATION bin + ARCHIVE DESTINATION ${SKBUILD_DATA_DIR}/lib + LIBRARY DESTINATION ${SKBUILD_DATA_DIR}/lib + RUNTIME DESTINATION ${SKBUILD_DATA_DIR}/bin ) -install(FILES galario.h galario_py.h galario_defs.h DESTINATION include) +install(FILES galario.h galario_py.h galario_defs.h DESTINATION ${SKBUILD_DATA_DIR}/include) ### # testing