diff --git a/.github/workflows/documentation.yml b/.github/workflows/documentation.yml index 2f9ce0a..6beef2e 100644 --- a/.github/workflows/documentation.yml +++ b/.github/workflows/documentation.yml @@ -4,9 +4,6 @@ on: push: branches: - main - pull_request: - branches: - - main workflow_dispatch: permissions: diff --git a/.github/workflows/package-publish.yml b/.github/workflows/package-publish.yml index 8df4c84..349ad7e 100644 --- a/.github/workflows/package-publish.yml +++ b/.github/workflows/package-publish.yml @@ -1,26 +1,30 @@ -name: Build and Publish Wheel +name: Build and Publish Python Packages on: # release: # types: [published] - push: + push: # Only for testing while publish-to-pypi is commented out branches: - main +env: + MACOSX_DEPLOYMENT_TARGET: "10.12" + CIBW_BUILD: "cp310-* cp311-* cp312-*" + jobs: build_wheels: name: Build wheels on ${{ matrix.os }} runs-on: ${{ matrix.os }} strategy: matrix: - # macos-13 is an intel runner, macos-14 is apple silicon - os: [ubuntu-latest, macos-13, macos-14] - python_version: ["3.10", "3.11", "3.12"] + os: [ubuntu-latest, windows-latest, macos-13, macos-latest] steps: - uses: actions/checkout@v4 - uses: actions/setup-python@v5 with: - python-version: ${{ matrix.python_version }} + python-version: "3.12" + - name: Install cibuildwheel + run: python -m pip install cibuildwheel==2.22.0 - name: Install setuptools run: | python -m pip install --upgrade pip @@ -29,38 +33,36 @@ jobs: rustc --version python -m pip install build setuptools setuptools-rust - name: Build wheels - run: - python -m build --outdir py_dist - - name: Store the distribution packages + run: python -m cibuildwheel --output-dir py_dist + - name: Store the compiled packages uses: actions/upload-artifact@v4 with: - name: esat-wheels-${{ matrix.os }}-py${{matrix.python_version}} + name: esat-wheels-${{ matrix.os }}-${{ strategy.job-index }} path: py_dist/ - build_windows_wheel: - name: Build wheels on windows-latest - runs-on: windows-latest - strategy: - matrix: - python_version: [ "3.10", "3.11", "3.12" ] + publish-to-testpypi: + name: Publish Python 🐍 distribution 📦 to TestPyPI + needs: + - build_wheels + runs-on: ubuntu-latest + environment: + name: testpypi + url: https://test.pypi.org/p/esat + permissions: + id-token: write steps: - - uses: actions/checkout@v4 - - uses: actions/setup-python@v5 - with: - python-version: ${{ matrix.python_version }} - - name: Install setuptools - run: | - python -m pip install --upgrade pip - curl https://sh.rustup.rs -sSf | sh -s -- -y --default-toolchain=stable - echo "${HOME}/.cargo/bin" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append - python -m pip install build setuptools setuptools-rust - - name: Build wheels - run: python -m build --outdir py_dist - - name: Store the distribution packages - uses: actions/upload-artifact@v4 + - name: Download all the dists + uses: actions/download-artifact@v4 with: - name: esat-wheels-${{ matrix.os }}-py${{matrix.python_version}} + pattern: esat-wheels-* + merge-multiple: true path: py_dist/ + - name: Publish distribution 📦 to TestPyPI + uses: pypa/gh-action-pypi-publish@release/v1 + with: + packages-dir: py_dist/ + skip-existing: true + repository-url: https://test.pypi.org/legacy/ # publish-to-pypi: # name: >- @@ -68,7 +70,7 @@ jobs: # if: startsWith(github.ref, 'refs/tags/') # only publish to PyPI on tag pushes # needs: # - build_wheels -# - build_windows_wheel +# - publish-to-testpypi # runs-on: ubuntu-latest # environment: # name: pypi @@ -79,11 +81,16 @@ jobs: # - name: Download all the dists # uses: actions/download-artifact@v4 # with: -# name: python-package-distributions +# pattern: esat-wheels-* +# merge-multiple: true # path: py_dist/ # - name: Publish distribution 📦 to PyPI # uses: pypa/gh-action-pypi-publish@release/v1 -# +# with: +# packages-dir: py_dist/ + +# Currently not intending on using automated github-release as the primary trigger for pypi publishing is by creating +# a new github version release. This is done manually by the developer. # github-release: # name: >- # Sign the Python 🐍 distribution 📦 with Sigstore @@ -126,31 +133,3 @@ jobs: # gh release upload # '${{ github.ref_name }}' py_dist/** # --repo '${{ github.repository }}' - - - publish-to-testpypi: - name: Publish Python 🐍 distribution 📦 to TestPyPI - needs: - - build_wheels - - build_windows_wheel - runs-on: ubuntu-latest - - environment: - name: testpypi - url: https://test.pypi.org/p/esat - - permissions: - id-token: write # IMPORTANT: mandatory for trusted publishing - - steps: - - name: Download all the dists - uses: actions/download-artifact@v4 - with: - pattern: esat-wheels-* - merge-multiple: true - path: py_dist/ - - name: Publish distribution 📦 to TestPyPI - uses: pypa/gh-action-pypi-publish@release/v1 - with: - packages-dir: py_dist/ - repository-url: https://test.pypi.org/legacy/ \ No newline at end of file diff --git a/.github/workflows/python-package.yml b/.github/workflows/python-package.yml index c2989f8..2b3dfa7 100644 --- a/.github/workflows/python-package.yml +++ b/.github/workflows/python-package.yml @@ -1,9 +1,13 @@ -name: Build and Publish Wheel +name: Build and Publish Artifacts on: push: branches: - - main + - dev + +env: + MACOSX_DEPLOYMENT_TARGET: "10.12" + CIBW_BUILD: "cp310-* cp311-* cp312-*" jobs: build_wheels: @@ -11,49 +15,76 @@ jobs: runs-on: ${{ matrix.os }} strategy: matrix: - # macos-13 is an intel runner, macos-14 is apple silicon - os: [ubuntu-latest, macos-13, macos-14] - python_version: ["3.10", "3.11", "3.12"] + os: [ ubuntu-latest, windows-latest, macos-13, macos-latest ] steps: - uses: actions/checkout@v4 - uses: actions/setup-python@v5 with: - python-version: ${{ matrix.python_version }} - - name: Install setuptools - run: | - python -m pip install --upgrade pip - curl https://sh.rustup.rs -sSf | sh -s -- -y --default-toolchain=stable - echo "PATH=${PATH}:${HOME}/.cargo/bin" >> "$GITHUB_ENV" - rustc --version - python -m pip install build setuptools setuptools-rust - - name: Build wheels - run: - python -m build --outdir wheelhouse - - uses: actions/upload-artifact@v4 - with: - name: esat-wheels-${{ matrix.os }}-py${{matrix.python_version}} - path: ./wheelhouse/*.whl - - build_windows_wheel: - name: Build wheels on windows-latest - runs-on: windows-latest - strategy: - matrix: - python_version: [ "3.10", "3.11", "3.12" ] - steps: - - uses: actions/checkout@v4 - - uses: actions/setup-python@v5 - with: - python-version: ${{ matrix.python_version }} + python-version: "3.12" + - name: Install cibuildwheel + run: python -m pip install cibuildwheel==2.22.0 - name: Install setuptools run: | python -m pip install --upgrade pip curl https://sh.rustup.rs -sSf | sh -s -- -y --default-toolchain=stable - echo "${HOME}/.cargo/bin" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append + echo "PATH=${PATH}:${HOME}/.cargo/bin" >> "$GITHUB_ENV" + rustc --version python -m pip install build setuptools setuptools-rust - name: Build wheels - run: python -m build --outdir wheelhouse + run: python -m cibuildwheel --output-dir wheelhouse - uses: actions/upload-artifact@v4 with: - name: esat-wheels-windows-py${{matrix.python_version}} + name: esat-wheels-${{ matrix.os }}-py${{matrix.python_version}} path: ./wheelhouse/*.whl + +# build_wheels: +# name: Build wheels on ${{ matrix.os }} +# runs-on: ${{ matrix.os }} +# strategy: +# matrix: +# # macos-13 is an intel runner, macos-14 is apple silicon +# os: [ubuntu-latest, macos-13, macos-14] +# python_version: ["3.10", "3.11", "3.12"] +# steps: +# - uses: actions/checkout@v4 +# - uses: actions/setup-python@v5 +# with: +# python-version: ${{ matrix.python_version }} +# - name: Install setuptools +# run: | +# python -m pip install --upgrade pip +# curl https://sh.rustup.rs -sSf | sh -s -- -y --default-toolchain=stable +# echo "PATH=${PATH}:${HOME}/.cargo/bin" >> "$GITHUB_ENV" +# rustc --version +# python -m pip install build setuptools setuptools-rust +# - name: Build wheels +# run: +# python -m build --outdir wheelhouse +# - uses: actions/upload-artifact@v4 +# with: +# name: esat-wheels-${{ matrix.os }}-py${{matrix.python_version}} +# path: ./wheelhouse/*.whl +# +# build_windows_wheel: +# name: Build wheels on windows-latest +# runs-on: windows-latest +# strategy: +# matrix: +# python_version: [ "3.10", "3.11", "3.12" ] +# steps: +# - uses: actions/checkout@v4 +# - uses: actions/setup-python@v5 +# with: +# python-version: ${{ matrix.python_version }} +# - name: Install setuptools +# run: | +# python -m pip install --upgrade pip +# curl https://sh.rustup.rs -sSf | sh -s -- -y --default-toolchain=stable +# echo "${HOME}/.cargo/bin" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append +# python -m pip install build setuptools setuptools-rust +# - name: Build wheels +# run: python -m build --outdir wheelhouse +# - uses: actions/upload-artifact@v4 +# with: +# name: esat-wheels-windows-py${{matrix.python_version}} +# path: ./wheelhouse/*.whl diff --git a/README.md b/README.md index 2ebc354..b016b86 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ # Environmental Source Apportionment Toolkit (ESAT) -Last Update: 08-15-2024 +Last Update: 12-09-2024 ## Table of Contents - [Description](#description) @@ -38,24 +38,25 @@ ESAT supports python version 3.10, 3.11, and 3.12. As the python package contain specific versions, supporting Mac Intel, Mac M1+, Linux, and Windows. ### Documentation -The Python API and CLI documentation can be found at the Github ESAT IO site: [https://quanted.github.io/esat/](https://quanted.github.io/esat/) +The Python API and CLI documentation can be found at the GitHub ESAT IO site: [https://quanted.github.io/esat/](https://quanted.github.io/esat/) ### Installation The ESAT python package contains all compiled code and required dependencies and can be installed using pip ```bash -pip install esat-VERSION-OS.whl +pip install esat ``` -where the VERSION is the code version, such as 2024.1.0, and OS is operating system targeted -compiled version, such as cp312-cp312-win_amd64. If an error message appears during installation stating that the -package is not supported check that the correct OS and python version are being installed for that system. +which will install the latest version that supports and is available for your python version and OS. -The latest version of the ESAT python package can be found on the github actions page, for users who are signed into github, +Development versions of ESAT can be found on the GitHub actions page, for logged-in users, under the 'Build and Publish Wheel' workflow. The latest version of the package will be available as an artifact for -download in the 'Artifacts' section of the completed workflow. +download in the 'Artifacts' section of the completed workflow. There wheel files can be found for specific versions +of python and supported operating systems. -When the package becomes available on pypi, the package will be able to be installed with +If an error message appears during installation stating that the +package is not supported check that the correct OS and python version are being installed for that system. The python +wheels can be installed directly using ```bash -pip install esat +pip install ``` The esat python package is recommended to be installed in its own dedicated python virtual environment or conda environment. diff --git a/eval/factor_comparison.py b/eval/factor_comparison.py index 5147cf6..de275e4 100644 --- a/eval/factor_comparison.py +++ b/eval/factor_comparison.py @@ -450,3 +450,41 @@ def combine_factors(self, factors, model_correlation, model_contributions, facto r_avg_3 = np.mean(r_values_3) return factors, r_avg, r_values, r_avg_2, r_values_2, r_avg_3, r_values_3 +# class FactorCompareV2: +# """ +# +# Parameters +# ---------- +# base_model : BaseModel +# The base model to compare against. +# models : list +# A list of models to compare against the base model. +# method : str +# Correlation method to use +# """ +# def __init__(self, base_model, models, method: str = "all"): +# self.base_model = base_model +# self.models = models +# self.method = method +# self.base_factors = base_model.factors +# self.base_features = base_model.features +# +# self.model_results = {} +# +# self.factor_map = None +# +# def compare(self, verbose: bool = True): +# """ +# +# Parameters +# ---------- +# verbose +# +# Returns +# ------- +# +# """ +# base_mean_W = np.mean(self.base_model.W, axis=0)[0] +# base_mass_matrix = (base_mean_W*self.base_model.H)/np.sum(base_mean_W*self.base_model.H) + + diff --git a/paper/paper.bib b/paper/paper.bib index 14d6bfe..5f8ea24 100644 --- a/paper/paper.bib +++ b/paper/paper.bib @@ -42,7 +42,7 @@ @article{Ding:2008 } @article{Jiang:2019, - title={Application of positive matrix factorization to identify potential sources of water quality deterioration of Huaihe River, China}, + title={Application of positive matrix factorization to identify potential sources of water quality deterioration of {H}uaihe {R}iver, {C}hina}, author={Jiang, J. and Khan, A.U. and Shi, B.}, journal={Applied Water Science}, volume={9}, @@ -55,7 +55,7 @@ @article{Jiang:2019 @article{Mamum:2021, AUTHOR = {Mamun, Md and An, Kwang-Guk}, - TITLE = {Application of Multivariate Statistical Techniques and Water Quality Index for the Assessment of Water Quality and Apportionment of Pollution Sources in the Yeongsan River, South Korea}, + TITLE = {Application of {M}ultivariate {S}tatistical {T}echniques and {W}ater {Q}uality {I}ndex for the {A}ssessment of {W}ater {Q}uality and {A}pportionment of {P}ollution {S}ources in the {Y}eongsan {R}iver, {S}outh {K}orea}, JOURNAL = {International Journal of Environmental Research and Public Health}, VOLUME = {18}, YEAR = {2021}, @@ -108,7 +108,7 @@ @article{Paatero:2014 @misc{PMF5:2014, author={United States EPA}, - title={Positive Matrix Factorization Model for Environmental Data Analyses}, + title={Positive {M}atrix {F}actorization {M}odel for {E}nvironmental {D}ata {A}nalyses}, year={2014}, url={https://www.epa.gov/air-research/positive-matrix-factorization-model-environmental-data-analyses} } diff --git a/pyproject.toml b/pyproject.toml index c5724eb..a698987 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -23,8 +23,11 @@ classifiers = [ "Programming Language :: Python :: Implementation :: PyPy", ] dynamic = ["dependencies"] +readme = "README.md" +license = {file = "LICENSE"} [project.urls] +Documentation = "https://quanted.github.io/esat/" Repository = "https://github.com/quanted/esat.git" Issues = "https://github.com/quanted/esat/issues" @@ -32,6 +35,13 @@ Issues = "https://github.com/quanted/esat/issues" package-dir = {"esat" = "esat", "esat_eval" = "eval"} include-package-data = true +[tool.cibuildwheel] +skip = "cp36-* cp37-* cp-38* cp-313* pp37-* *-manylinux_i686 *_ppc64le *_s390x *_universal2 *-musllinux_i686" +linux.before-all = "curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --profile minimal" +linux.environment = { PATH="$HOME/.cargo/bin:$PATH" } +macos.before-all = "curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --profile minimal" +windows.before-all = "rustup target add aarch64-pc-windows-msvc i586-pc-windows-msvc i686-pc-windows-msvc x86_64-pc-windows-msvc" + [tool.setuptools.dynamic] dependencies = {file = ["requirements.txt"]}