diff --git a/.cirrus.yml b/.cirrus.yml deleted file mode 100644 index 5d9646d..0000000 --- a/.cirrus.yml +++ /dev/null @@ -1,75 +0,0 @@ -compile_openblas_macos_arm64_task: - name: Compile OpenBLAS on MacOS arm64 - alias: compile_openblas_macos_arm64 - trigger_type: manual - macos_instance: - image: ghcr.io/cirruslabs/macos-monterey-xcode:latest - env: - MACOSX_DEPLOYMENT_TARGET: "11.0" - clone_script: - - echo SKIP CLONE - install_requirements_script: - - brew install p7zip - compile_openblas_arm64_script: - - curl -L -o OpenBLAS-0.3.21.tar.gz https://github.com/xianyi/OpenBLAS/releases/download/v0.3.21/OpenBLAS-0.3.21.tar.gz - - tar -xzf OpenBLAS-0.3.21.tar.gz - - make -C OpenBLAS-0.3.21 TARGET=ARMV8 DYNAMIC_ARCH=1 - - make install -C OpenBLAS-0.3.21 PREFIX=${CIRRUS_WORKING_DIR}/OpenBLAS - - 7z a OpenBLAS_macos_arm64.zip ./OpenBLAS/* - - curl -X DELETE -H "Accept:application/vnd.github+json" -H "Authorization:Bearer ${REPO_TOKEN}" -H "X-GitHub-Api-Version:2022-11-28" https://api.github.com/repos/daducci/AMICO/actions/variables/CIRRUS_BUILD_ID - - curl -X POST -H "Accept:application/vnd.github+json" -H "Authorization:Bearer ${REPO_TOKEN}" -H "X-GitHub-Api-Version:2022-11-28" https://api.github.com/repos/daducci/AMICO/actions/variables -d '{"name":"CIRRUS_BUILD_ID","value":"'"$CIRRUS_BUILD_ID"'"}' - compiled_openblas_artifacts: - path: 'OpenBLAS_macos_arm64.zip' - -build_macos_arm64_wheels_task: - name: Build MacOS arm64 wheels - alias: build_macos_arm64_wheels - only_if: ${CIRRUS_CHANGE_IN_REPO} != ${CIRRUS_LAST_GREEN_CHANGE} - macos_instance: - image: ghcr.io/cirruslabs/macos-monterey-xcode:latest - matrix: - - env: - CP: "38" - - env: - CP: "39" - - env: - CP: "310" - - env: - CP: "311" - env: - MACOSX_DEPLOYMENT_TARGET: 11.0 - PATH: ${PATH}:/opt/homebrew/opt/python@3.10/bin - CIBW_PLATFORM: macos - CIBW_BUILD: cp${CP}-macosx_arm64 - CIBW_ARCHS_MACOS: arm64 - CIBW_REPAIR_WHEEL_COMMAND_MACOS: > - DYLD_LIBRARY_PATH=${CIRRUS_WORKING_DIR}/OpenBLAS/lib delocate-wheel --require-archs {delocate_archs} -w {dest_dir} -v {wheel} - install_requirements_script: - - brew install p7zip - - brew install jq - - brew install python@3.10 - - python3.10 -m pip install cibuildwheel==2.15.0 - download_compiled_openblas_script: - - CIRRUS_BUILD_ID=$(curl -H "Accept:application/vnd.github+json" -H "Authorization:Bearer ${REPO_TOKEN}" -H "X-GitHub-Api-Version:2022-11-28" https://api.github.com/repos/daducci/AMICO/actions/variables/CIRRUS_BUILD_ID | jq -r .value) - - curl -L -o OpenBLAS.zip https://api.cirrus-ci.com/v1/artifact/build/${CIRRUS_BUILD_ID}/compile_openblas_macos_arm64/compiled_openblas/OpenBLAS_macos_arm64.zip - - 7z x OpenBLAS.zip -o"OpenBLAS" - set_up_configuration_file_script: - - python3.10 setup_site.py openblas openblas ${CIRRUS_WORKING_DIR}/OpenBLAS/lib ${CIRRUS_WORKING_DIR}/OpenBLAS/include - run_cibuildwheel_script: - - cibuildwheel - wheels_macos_arm64_artifacts: - path: './wheelhouse/*.whl' - -trigger_github_workflow_task: - name: Trigger GitHub workflow - only_if: ${CIRRUS_CHANGE_IN_REPO} != ${CIRRUS_LAST_GREEN_CHANGE} - depends_on: build_macos_arm64_wheels - macos_instance: - image: ghcr.io/cirruslabs/macos-monterey-xcode:latest - clone_script: - - echo SKIP CLONE - install_requirements_script: - - brew install jq - trigger_script: - - CHECK_ID_MACOS_ARM64=$(curl -H "Accept:application/vnd.github+json" -H "Authorization:Bearer ${REPO_TOKEN}" -H "X-GitHub-Api-Version:2022-11-28" https://api.github.com/repos/daducci/AMICO/actions/variables/CHECK_ID_MACOS_ARM64 | jq -r .value) - - curl -X POST -H "Accept:application/vnd.github+json" -H "Authorization:Bearer ${REPO_TOKEN}" -H "X-GitHub-Api-Version:2022-11-28" https://api.github.com/repos/daducci/AMICO/actions/workflows/macos_arm64_wheels.yml/dispatches -d '{"ref":"'"$CIRRUS_BRANCH"'","inputs":{"cirrus_build_id":"'"$CIRRUS_BUILD_ID"'","check_id_macos_arm64":"'"$CHECK_ID_MACOS_ARM64"'"}}' diff --git a/.github/workflows/build_wheels.yml b/.github/workflows/build_wheels.yml index 0ab7780..c3cf833 100644 --- a/.github/workflows/build_wheels.yml +++ b/.github/workflows/build_wheels.yml @@ -9,27 +9,27 @@ jobs: build_windows_wheels: strategy: matrix: - py: [cp36, cp37, cp38, cp39, cp310, cp311] + py: [cp36, cp37, cp38, cp39, cp310, cp311, cp312] arch: - [AMD64, win_amd64, x64] - [x86, win32, x86] name: ${{ matrix.py }}-${{ matrix.arch[1] }} - runs-on: windows-2019 + runs-on: windows-latest steps: - name: Checkout - uses: actions/checkout@v4.0.0 + uses: actions/checkout@v4 - name: Download compiled OpenBLAS run: | - curl -L -o OpenBLAS-0.3.21.zip https://github.com/xianyi/OpenBLAS/releases/download/v0.3.21/OpenBLAS-0.3.21-${{ matrix.arch[2] }}.zip - 7z x OpenBLAS-0.3.21.zip -o"OpenBLAS" + curl -L -o OpenBLAS-0.3.27.zip https://github.com/OpenMathLib/OpenBLAS/releases/download/v0.3.27/OpenBLAS-0.3.27-${{ matrix.arch[2] }}.zip + 7z x OpenBLAS-0.3.27.zip -o"OpenBLAS" - name: Set up the configuration file run: | python setup_site.py openblas libopenblas ${{ github.workspace }}\OpenBLAS\lib ${{ github.workspace }}\OpenBLAS\include - name: Build wheel ${{ matrix.py }}-${{ matrix.arch[1] }} - uses: pypa/cibuildwheel@v2.15.0 + uses: pypa/cibuildwheel@v2.19.1 env: CIBW_PLATFORM: windows CIBW_BUILD: ${{ matrix.py }}-${{ matrix.arch[1] }} @@ -40,87 +40,128 @@ jobs: delvewheel repair --add-path ${{ github.workspace }}\OpenBLAS\bin -w {dest_dir} -v {wheel} - name: Upload artifacts - uses: actions/upload-artifact@v3.1.3 + uses: actions/upload-artifact@v4 with: - name: wheels_windows_${{ matrix.arch[0] }} + name: wheels_${{ matrix.py }}_${{ matrix.arch[1] }} path: ./wheelhouse/*.whl if-no-files-found: error - build_macos_x86_64_wheels: + build_macos_wheels: strategy: matrix: - py: [cp36, cp37, cp38, cp39, cp310, cp311] - arch: - - [x86_64, macosx_x86_64] - name: ${{ matrix.py }}-${{ matrix.arch[1] }} - runs-on: macos-11 + config: + [ + { + py: cp36, + arch: [x86_64, macosx_x86_64, 12.0, macos-12] + }, + { + py: cp37, + arch: [x86_64, macosx_x86_64, 12.0, macos-12] + }, + { + py: cp38, + arch: [x86_64, macosx_x86_64, 12.0, macos-12] + }, + { + py: cp39, + arch: [x86_64, macosx_x86_64, 12.0, macos-12] + }, + { + py: cp310, + arch: [x86_64, macosx_x86_64, 12.0, macos-12] + }, + { + py: cp311, + arch: [x86_64, macosx_x86_64, 12.0, macos-12] + }, + { + py: cp312, + arch: [x86_64, macosx_x86_64, 12.0, macos-12] + }, + { + py: cp38, + arch: [arm64, macosx_arm64, 12.0, macos-14] + }, + { + py: cp39, + arch: [arm64, macosx_arm64, 12.0, macos-14] + }, + { + py: cp310, + arch: [arm64, macosx_arm64, 12.0, macos-14] + }, + { + py: cp311, + arch: [arm64, macosx_arm64, 12.0, macos-14] + }, + { + py: cp312, + arch: [arm64, macosx_arm64, 12.0, macos-14] + } + ] + name: ${{ matrix.config.py }}-${{ matrix.config.arch[1] }} + runs-on: ${{ matrix.config.arch[3] }} + if: steps: - name: Checkout - uses: actions/checkout@v4.0.0 + uses: actions/checkout@v4 - name: Download compiled OpenBLAS - uses: dawidd6/action-download-artifact@v2.27.0 + uses: actions/download-artifact@v4 with: - workflow: compile_openblas_macos_x86_64.yml - workflow_conclusion: success - commit: ${{github.event.pull_request.head.sha}} - name: OpenBLAS_macos_${{ matrix.arch[0] }} + github-token: ${{ secrets.GH_PAT }} + run-id: ${{ secrets.OPENBLAS_MACOS_ARTIFACTS_RUN_ID }} + name: OpenBLAS_macos_${{ matrix.config.arch[0] }} path: OpenBLAS - search_artifacts: true + + - name: Install pipx # NOTE: required only for arm64 + if: startsWith(matrix.config.arch[0], 'arm64') + run: | + brew install pipx - name: Set up the configuration file run: | python3 setup_site.py openblas openblas ${{ github.workspace }}/OpenBLAS/lib ${{ github.workspace }}/OpenBLAS/include - - name: Build wheel ${{ matrix.py }}-${{ matrix.arch[1] }} - uses: pypa/cibuildwheel@v2.15.0 + - name: Build wheel ${{ matrix.config.py }}-${{ matrix.config.arch[1] }} + uses: pypa/cibuildwheel@v2.19.1 env: - MACOSX_DEPLOYMENT_TARGET: 10.9 + CIBW_ENVIRONMENT_MACOS: > + MACOSX_DEPLOYMENT_TARGET=${{ matrix.config.arch[2] }} CIBW_PLATFORM: macos - CIBW_BUILD: ${{ matrix.py }}-${{ matrix.arch[1] }} - CIBW_ARCHS_MACOS: ${{ matrix.arch[0] }} + CIBW_BUILD: ${{ matrix.config.py }}-${{ matrix.config.arch[1] }} + CIBW_ARCHS_MACOS: ${{ matrix.config.arch[0] }} CIBW_REPAIR_WHEEL_COMMAND_MACOS: > DYLD_LIBRARY_PATH=${{ github.workspace }}/OpenBLAS/lib delocate-wheel --require-archs {delocate_archs} -w {dest_dir} -v {wheel} - name: Upload artifacts - uses: actions/upload-artifact@v3.1.3 + uses: actions/upload-artifact@v4 with: - name: wheels_macos_${{ matrix.arch[0] }} + name: wheels_${{ matrix.config.py }}_${{ matrix.config.arch[1] }} path: ./wheelhouse/*.whl if-no-files-found: error - create_macos_arm64_check: - name: Create MacOS arm64 check - runs-on: ubuntu-20.04 - steps: - - name: Create check - run: | - curl -X DELETE -H "Accept:application/vnd.github+json" -H "Authorization:Bearer ${{ secrets.REPO_TOKEN }}" -H "X-GitHub-Api-Version:2022-11-28" https://api.github.com/repos/daducci/AMICO/actions/variables/CHECK_ID_MACOS_ARM64 - CHECK_ID_MACOS_ARM64=$(curl -X POST -H "Accept:application/vnd.github+json" -H "Authorization:Bearer ${{ github.token }}" -H "X-GitHub-Api-Version:2022-11-28" https://api.github.com/repos/daducci/AMICO/check-runs -d '{"name":"cp*-macosx_arm64","status":"in_progress","head_sha":"'"${{ github.sha }}"'"}' | jq -r .id) - curl -X POST -H "Accept:application/vnd.github+json" -H "Authorization:Bearer ${{ secrets.REPO_TOKEN }}" -H "X-GitHub-Api-Version:2022-11-28" https://api.github.com/repos/daducci/AMICO/actions/variables -d '{"name":"CHECK_ID_MACOS_ARM64","value":"'"$CHECK_ID_MACOS_ARM64"'"}' - build_linux_wheels: strategy: matrix: - py: [cp36, cp37, cp38, cp39, cp310, cp311] + py: [cp36, cp37, cp38, cp39, cp310, cp311, cp312] arch: - [x86_64, manylinux_x86_64, amd64] - [aarch64, manylinux_aarch64, arm64] name: ${{ matrix.py }}-${{ matrix.arch[1] }} - runs-on: ubuntu-20.04 + runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v4.0.0 + uses: actions/checkout@v4 - name: Download compiled OpenBLAS - uses: dawidd6/action-download-artifact@v2.27.0 + uses: actions/download-artifact@v4 with: - workflow: compile_openblas_linux.yml - workflow_conclusion: success - commit: ${{github.event.pull_request.head.sha}} + github-token: ${{ secrets.GH_PAT }} + run-id: ${{ secrets.OPENBLAS_LINUX_ARTIFACTS_RUN_ID }} name: OpenBLAS_linux_${{ matrix.arch[0] }} path: OpenBLAS - search_artifacts: true - name: Set up the configuration file run: | # NOTE: need to add '/host' because compilation is done in a Docker container @@ -132,7 +173,7 @@ jobs: platforms: ${{ matrix.arch[2] }} - name: Build wheel ${{ matrix.py }}-${{ matrix.arch[1] }} - uses: pypa/cibuildwheel@v2.15.0 + uses: pypa/cibuildwheel@v2.19.1 env: CIBW_PLATFORM: linux CIBW_BUILD: ${{ matrix.py }}-${{ matrix.arch[1] }} @@ -141,18 +182,18 @@ jobs: LD_LIBRARY_PATH=/host${{ github.workspace }}/OpenBLAS/lib auditwheel repair -w {dest_dir} {wheel} - name: Upload artifacts - uses: actions/upload-artifact@v3.1.3 + uses: actions/upload-artifact@v4 with: - name: wheels_linux_${{ matrix.arch[0] }} + name: wheels_${{ matrix.py }}_${{ matrix.arch[1] }} path: ./wheelhouse/*.whl if-no-files-found: error build_source_distribution: name: sdist - runs-on: ubuntu-20.04 + runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v4.0.0 + uses: actions/checkout@v4 - name: Set up the configuration file run: | @@ -165,8 +206,19 @@ jobs: python -m build --sdist - name: Upload artifacts - uses: actions/upload-artifact@v3.1.3 + uses: actions/upload-artifact@v4 with: name: sdist path: ./dist/*.tar.gz if-no-files-found: error + + run_id: + name: Create/Update WHEELS_ARTIFACTS_RUN_ID secret + runs-on: ubuntu-latest + needs: [build_windows_wheels, build_macos_wheels, build_linux_wheels, build_source_distribution] + steps: + - uses: actions/checkout@v4 + - run: | + gh secret set WHEELS_ARTIFACTS_RUN_ID --body ${{ github.run_id }} + env: + GH_TOKEN: ${{ secrets.GH_PAT }} diff --git a/.github/workflows/compile_openblas_linux.yml b/.github/workflows/compile_openblas_linux.yml index acb8c9b..93d91fa 100644 --- a/.github/workflows/compile_openblas_linux.yml +++ b/.github/workflows/compile_openblas_linux.yml @@ -9,7 +9,7 @@ jobs: - [x86_64, manylinux2014_x86_64, HASWELL, amd64] - [aarch64, manylinux2014_aarch64, ARMV8, arm64] name: ${{ matrix.arch[0] }} - runs-on: ubuntu-20.04 + runs-on: ubuntu-latest timeout-minutes: 600 # NOTE: need this to compile the arm64 version steps: - name: Set up QEMU @@ -19,16 +19,27 @@ jobs: - name: Compile OpenBLAS run: | - curl -L -o OpenBLAS-0.3.21.tar.gz https://github.com/xianyi/OpenBLAS/releases/download/v0.3.21/OpenBLAS-0.3.21.tar.gz - tar -xzf OpenBLAS-0.3.21.tar.gz + curl -L -o OpenBLAS-0.3.27.tar.gz https://github.com/OpenMathLib/OpenBLAS/releases/download/v0.3.27/OpenBLAS-0.3.27.tar.gz + tar -xzf OpenBLAS-0.3.27.tar.gz docker create --name=openblas_${{ matrix.arch[0] }} -i --volume=${GITHUB_WORKSPACE}:/host quay.io/pypa/${{ matrix.arch[1] }}:latest /bin/bash docker start openblas_${{ matrix.arch[0] }} - docker exec -i openblas_${{ matrix.arch[0] }} sh -c "make -C /host/OpenBLAS-0.3.21 TARGET=${{ matrix.arch[2] }} DYNAMIC_ARCH=1" - docker exec -i openblas_${{ matrix.arch[0] }} sh -c "make install -C /host/OpenBLAS-0.3.21 PREFIX=/host/OpenBLAS" + docker exec -i openblas_${{ matrix.arch[0] }} sh -c "make -C /host/OpenBLAS-0.3.27 TARGET=${{ matrix.arch[2] }} DYNAMIC_ARCH=1" + docker exec -i openblas_${{ matrix.arch[0] }} sh -c "make install -C /host/OpenBLAS-0.3.27 PREFIX=/host/OpenBLAS" - name: Upload artifacts - uses: actions/upload-artifact@v3.1.3 + uses: actions/upload-artifact@v4 with: name: OpenBLAS_linux_${{ matrix.arch[0] }} path: ./OpenBLAS if-no-files-found: error + + run_id: + name: Create/Update OPENBLAS_LINUX_ARTIFACTS_RUN_ID secret + runs-on: ubuntu-latest + needs: [compile_openblas] + steps: + - uses: actions/checkout@v4 + - run: | + gh secret set OPENBLAS_LINUX_ARTIFACTS_RUN_ID --body ${{ github.run_id }} + env: + GH_TOKEN: ${{ secrets.GH_PAT }} diff --git a/.github/workflows/compile_openblas_macos.yml b/.github/workflows/compile_openblas_macos.yml new file mode 100644 index 0000000..eef9e11 --- /dev/null +++ b/.github/workflows/compile_openblas_macos.yml @@ -0,0 +1,40 @@ +name: Compile OpenBLAS on MacOS +run-name: Compile OpenBLAS on MacOS - ${{ github.sha }} +on: workflow_dispatch +jobs: + compile_openblas: + strategy: + matrix: + arch: + - [x86_64, SANDYBRIDGE, 12.0, macos-12] + - [arm64, ARMV8, 12.0, macos-14] + name: ${{ matrix.arch[0] }} + runs-on: ${{ matrix.arch[3] }} + steps: + - name: Compile OpenBLAS + env: + MACOSX_DEPLOYMENT_TARGET: ${{ matrix.arch[2] }} + run: | + curl -L -o OpenBLAS-0.3.27.tar.gz https://github.com/OpenMathLib/OpenBLAS/releases/download/v0.3.27/OpenBLAS-0.3.27.tar.gz + tar -xzf OpenBLAS-0.3.27.tar.gz + sudo ln -fs /usr/local/bin/gfortran-11 /usr/local/bin/gfortran + make -C OpenBLAS-0.3.27 TARGET=${{ matrix.arch[1] }} DYNAMIC_ARCH=1 + make install -C OpenBLAS-0.3.27 PREFIX=${GITHUB_WORKSPACE}/OpenBLAS + + - name: Upload artifacts + uses: actions/upload-artifact@v4 + with: + name: OpenBLAS_macos_${{ matrix.arch[0] }} + path: ./OpenBLAS + if-no-files-found: error + + run_id: + name: Create/Update OPENBLAS_MACOS_ARTIFACTS_RUN_ID secret + runs-on: ubuntu-latest + needs: [compile_openblas] + steps: + - uses: actions/checkout@v4 + - run: | + gh secret set OPENBLAS_MACOS_ARTIFACTS_RUN_ID --body ${{ github.run_id }} + env: + GH_TOKEN: ${{ secrets.GH_PAT }} diff --git a/.github/workflows/compile_openblas_macos_x86_64.yml b/.github/workflows/compile_openblas_macos_x86_64.yml deleted file mode 100644 index d2635da..0000000 --- a/.github/workflows/compile_openblas_macos_x86_64.yml +++ /dev/null @@ -1,28 +0,0 @@ -name: Compile OpenBLAS on MacOS x86_64 -run-name: Compile OpenBLAS on MacOS x86_64 - ${{ github.sha }} -on: workflow_dispatch -jobs: - compile_openblas: - strategy: - matrix: - arch: - - [x86_64, SANDYBRIDGE] - name: ${{ matrix.arch[0] }} - runs-on: macos-11 - steps: - - name: Compile OpenBLAS - env: - MACOSX_DEPLOYMENT_TARGET: "10.9" - run: | - curl -L -o OpenBLAS-0.3.21.tar.gz https://github.com/xianyi/OpenBLAS/releases/download/v0.3.21/OpenBLAS-0.3.21.tar.gz - tar -xzf OpenBLAS-0.3.21.tar.gz - sudo ln -fs /usr/local/bin/gfortran-11 /usr/local/bin/gfortran - make -C OpenBLAS-0.3.21 TARGET=${{ matrix.arch[1] }} DYNAMIC_ARCH=1 - make install -C OpenBLAS-0.3.21 PREFIX=${GITHUB_WORKSPACE}/OpenBLAS - - - name: Upload artifacts - uses: actions/upload-artifact@v3.1.3 - with: - name: OpenBLAS_macos_${{ matrix.arch[0] }} - path: ./OpenBLAS - if-no-files-found: error diff --git a/.github/workflows/macos_arm64_wheels.yml b/.github/workflows/macos_arm64_wheels.yml deleted file mode 100644 index c46470f..0000000 --- a/.github/workflows/macos_arm64_wheels.yml +++ /dev/null @@ -1,40 +0,0 @@ -name: MacOS arm64 wheels -run-name: MacOS arm64 wheels - ${{ github.sha }} -on: - workflow_dispatch: - inputs: - cirrus_build_id: - description: Cirrus CI build ID - required: true - type: number - check_id_macos_arm64: - description: Check ID MacOS arm64 - required: true - type: number -jobs: - download_macos_arm64_wheels: - name: '*-macosx_arm64' - runs-on: ubuntu-20.04 - steps: - - name: Download wheels from Cirrus CI - run: | - echo "DOWNLOAD_RESPONSE=$(curl -L -o wheels_macos_arm64.zip -w '%{http_code}' https://api.cirrus-ci.com/v1/artifact/build/${{ inputs.cirrus_build_id }}/build_macos_arm64_wheels/wheels_macos_arm64.zip)" >> $GITHUB_ENV - 7z x wheels_macos_arm64.zip - - - name: Upload artifacts - id: upload_artifacts - uses: actions/upload-artifact@v3.1.3 - with: - name: wheels_macos_arm64 - path: ./wheelhouse/*.whl - if-no-files-found: error - - - name: Complete MacOS arm64 check - if: env.DOWNLOAD_RESPONSE == 200 && steps.upload_artifacts.conclusion == 'success' - run: | - curl -X PATCH -H "Accept: application/vnd.github+json" -H "Authorization: Bearer ${{ github.token }}" -H "X-GitHub-Api-Version: 2022-11-28" https://api.github.com/repos/daducci/AMICO/check-runs/${{ inputs.check_id_macos_arm64 }} -d '{"name":"cp*-macosx_arm64","status":"completed","conclusion":"success"}' - - - name: Complete MacOS arm64 check - if: (failure() && steps.upload_artifacts.conclusion != 'success') || env.DOWNLOAD_RESPONSE != 200 - run: | - curl -X PATCH -H "Accept: application/vnd.github+json" -H "Authorization: Bearer ${{ github.token }}" -H "X-GitHub-Api-Version: 2022-11-28" https://api.github.com/repos/daducci/AMICO/check-runs/${{ inputs.check_id_macos_arm64 }} -d '{"name":"cp*-macosx_arm64","status":"completed","conclusion":"failure"}' diff --git a/.github/workflows/publish_on_pypi.yml b/.github/workflows/publish_on_pypi.yml index e2a58b4..c2af123 100644 --- a/.github/workflows/publish_on_pypi.yml +++ b/.github/workflows/publish_on_pypi.yml @@ -7,85 +7,23 @@ jobs: publish_on_pypi: name: Publish on PyPI if: github.event.release.prerelease == false - runs-on: ubuntu-20.04 + runs-on: ubuntu-latest environment: name: pypi url: https://pypi.org/project/dmri-amico permissions: id-token: write # IMPORTANT: this permission is mandatory for trusted publishing steps: - - name: Download windows_AMD64 wheels - uses: dawidd6/action-download-artifact@v2.27.0 + - name: Download artifacts + uses: actions/download-artifact@v4 with: - workflow: build_wheels.yml - workflow_conclusion: success - commit: ${{github.event.pull_request.head.sha}} - name: wheels_windows_AMD64 + github-token: ${{ secrets.GH_PAT }} + run-id: ${{ secrets.WHEELS_ARTIFACTS_RUN_ID }} path: dist - search_artifacts: true - - - name: Download windows_x86 wheels - uses: dawidd6/action-download-artifact@v2.27.0 - with: - workflow: build_wheels.yml - workflow_conclusion: success - commit: ${{github.event.pull_request.head.sha}} - name: wheels_windows_x86 - path: dist - search_artifacts: true - - - name: Download macos_x86_64 wheels - uses: dawidd6/action-download-artifact@v2.27.0 - with: - workflow: build_wheels.yml - workflow_conclusion: success - commit: ${{github.event.pull_request.head.sha}} - name: wheels_macos_x86_64 - path: dist - search_artifacts: true - - - name: Download macos_arm64 wheels - uses: dawidd6/action-download-artifact@v2.27.0 - with: - workflow: macos_arm64_wheels.yml - workflow_conclusion: success - commit: ${{github.event.pull_request.head.sha}} - name: wheels_macos_arm64 - path: dist - search_artifacts: true - - - name: Download linux_x86_64 wheels - uses: dawidd6/action-download-artifact@v2.27.0 - with: - workflow: build_wheels.yml - workflow_conclusion: success - commit: ${{github.event.pull_request.head.sha}} - name: wheels_linux_x86_64 - path: dist - search_artifacts: true - - - name: Download linux_aarch64 wheels - uses: dawidd6/action-download-artifact@v2.27.0 - with: - workflow: build_wheels.yml - workflow_conclusion: success - commit: ${{github.event.pull_request.head.sha}} - name: wheels_linux_aarch64 - path: dist - search_artifacts: true - - - name: Download source distribution - uses: dawidd6/action-download-artifact@v2.27.0 - with: - workflow: build_wheels.yml - workflow_conclusion: success - commit: ${{github.event.pull_request.head.sha}} - name: sdist - path: dist - search_artifacts: true + merge-multiple: true - name: Publish on PyPI - uses: pypa/gh-action-pypi-publish@v1.8.10 + uses: pypa/gh-action-pypi-publish@release/v1 with: skip-existing: true verbose: true @@ -94,87 +32,25 @@ jobs: publish_on_pypi_test: name: Publish on PyPI Test if: github.event.release.prerelease == true && contains(github.event.release.tag_name, 'rc') - runs-on: ubuntu-20.04 + runs-on: ubuntu-latest environment: name: testpypi url: https://test.pypi.org/project/dmri-amico permissions: id-token: write # IMPORTANT: this permission is mandatory for trusted publishing steps: - - name: Download windows_AMD64 wheels - uses: dawidd6/action-download-artifact@v2.27.0 - with: - workflow: build_wheels.yml - workflow_conclusion: success - commit: ${{github.event.pull_request.head.sha}} - name: wheels_windows_AMD64 - path: dist - search_artifacts: true - - - name: Download windows_x86 wheels - uses: dawidd6/action-download-artifact@v2.27.0 - with: - workflow: build_wheels.yml - workflow_conclusion: success - commit: ${{github.event.pull_request.head.sha}} - name: wheels_windows_x86 - path: dist - search_artifacts: true - - - name: Download macos_x86_64 wheels - uses: dawidd6/action-download-artifact@v2.27.0 - with: - workflow: build_wheels.yml - workflow_conclusion: success - commit: ${{github.event.pull_request.head.sha}} - name: wheels_macos_x86_64 - path: dist - search_artifacts: true - - - name: Download macos_arm64 wheels - uses: dawidd6/action-download-artifact@v2.27.0 - with: - workflow: macos_arm64_wheels.yml - workflow_conclusion: success - commit: ${{github.event.pull_request.head.sha}} - name: wheels_macos_arm64 - path: dist - search_artifacts: true - - - name: Download linux_x86_64 wheels - uses: dawidd6/action-download-artifact@v2.27.0 - with: - workflow: build_wheels.yml - workflow_conclusion: success - commit: ${{github.event.pull_request.head.sha}} - name: wheels_linux_x86_64 - path: dist - search_artifacts: true - - - name: Download linux_aarch64 wheels - uses: dawidd6/action-download-artifact@v2.27.0 - with: - workflow: build_wheels.yml - workflow_conclusion: success - commit: ${{github.event.pull_request.head.sha}} - name: wheels_linux_aarch64 - path: dist - search_artifacts: true - - - name: Download source distribution - uses: dawidd6/action-download-artifact@v2.27.0 + - name: Download artifacts + uses: actions/download-artifact@v4 with: - workflow: build_wheels.yml - workflow_conclusion: success - commit: ${{github.event.pull_request.head.sha}} - name: sdist + github-token: ${{ secrets.GH_PAT }} + run-id: ${{ secrets.WHEELS_ARTIFACTS_RUN_ID }} path: dist - search_artifacts: true + merge-multiple: true - name: Publish on PyPI Test - uses: pypa/gh-action-pypi-publish@v1.8.10 + uses: pypa/gh-action-pypi-publish@release/v1 with: - repository_url: https://test.pypi.org/legacy/ + repository-url: https://test.pypi.org/legacy/ skip-existing: true verbose: true print-hash: true diff --git a/CHANGELOG.md b/CHANGELOG.md index 344430b..791b029 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,23 @@ # Change Log ### All notable changes to `AMICO` will be documented in this file. -## `v2.0.0`
_2023-09-21_ +## `v2.0.2`
_2024-07-04_ +### ✨Added +- Added `cp312` wheels to github actions + +### 🛠️Changed +- Restict the `numpy` version to `<2.0.0` (due to `dipy` problems) +- Parameters in the `set()` method of the models have now default values +- `MacOS arm64` wheels are now compiled with GitHub Actions instead of Cirrus CI + +### 🐛Fixed +- Link to installation guide in `README.md` +- Improved `print()` statements when running from `Jupyter notebooks` + +--- +--- + +## `v2.0.1`
_2023-09-21_ ### 🛠️Changed - Bump `dmri-dicelib` to `v1.0.1` diff --git a/LICENSE b/LICENSE index bf230f3..2e43c8d 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ ################################################################################ AMICO software license agreement - Version 2.0.0, 24 July 2023 + Version 2, 24 July 2023 ################################################################################ ------------------------------------PREAMBLE------------------------------------ diff --git a/README.md b/README.md index fbbf3ec..ebe212b 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,7 @@ ### Implementation of the linear framework for Accelerated Microstructure Imaging via Convex Optimization (AMICO) described in [Daducci, Alessandro, et al. 2015](https://doi.org/10.1016/j.neuroimage.2014.10.026) ## Documentation -The documentation, including the [installation guide](https://github.com/daducci/AMICO/wiki/installation) as well as a series of demos/tutorials to show how to use AMICO to fit different models to your data, can be found in the [wiki](https://github.com/daducci/AMICO/wiki). +The documentation, including the [installation guide](https://github.com/daducci/AMICO/wiki/How-to-install-AMICO) as well as a series of demos/tutorials to show how to use AMICO to fit different models to your data, can be found in the [wiki](https://github.com/daducci/AMICO/wiki). ## Support For questions, requesting assistance, suggesting enhancements or new ideas as well as for reporting bugs, please [open an issue](https://github.com/daducci/AMICO/issues). diff --git a/amico/__init__.py b/amico/__init__.py index 48bbbd1..ff05358 100755 --- a/amico/__init__.py +++ b/amico/__init__.py @@ -1,12 +1,12 @@ -from __future__ import absolute_import, division, print_function +from amico.core import Evaluation, setup +from amico.util import set_verbose, get_verbose +# from amico import core +# from amico import scheme +# from amico import lut +# from amico import models +# from amico import util -from .core import Evaluation, setup -from .util import set_verbose, get_verbose -from . import core -from . import scheme -from . import lut -from . import models -from . import util +__all__ = ['Evaluation', 'setup', 'set_verbose', 'get_verbose'] try: from importlib.metadata import version diff --git a/amico/core.py b/amico/core.py index 04c2673..3c0b39c 100644 --- a/amico/core.py +++ b/amico/core.py @@ -1,5 +1,3 @@ -from __future__ import absolute_import, division, print_function - import numpy as np import time import glob diff --git a/amico/lut.pyx b/amico/lut.pyx index 6434826..c18020e 100644 --- a/amico/lut.pyx +++ b/amico/lut.pyx @@ -1,8 +1,6 @@ # distutils: language = c++ # cython: language_level = 3 -from __future__ import absolute_import, division, print_function - import numpy as np from os import makedirs import sys diff --git a/amico/models.pyx b/amico/models.pyx index 26712e0..73e19f2 100644 --- a/amico/models.pyx +++ b/amico/models.pyx @@ -1,8 +1,6 @@ # distutils: language = c++ # cython: language_level = 3 -from __future__ import absolute_import, division, print_function - import numpy as np from os import environ from os.path import join as pjoin @@ -40,13 +38,13 @@ cdef void _init_multithread_progress(int nthreads): @cython.boundscheck(False) @cython.wraparound(False) -cdef void _update_multithread_progress(int thread_id) nogil: +cdef void _update_multithread_progress(int thread_id) noexcept nogil: global _MULTITHREAD_PROGRESS_VIEW _MULTITHREAD_PROGRESS_VIEW[thread_id] += 1 @cython.boundscheck(False) @cython.wraparound(False) -cdef void _compute_rmse(double [::1, :]A_view, double [::1]y_view, double [::1]x_view, double *y_est_view, double *rmse_view) nogil: +cdef void _compute_rmse(double [::1, :]A_view, double [::1]y_view, double [::1]x_view, double *y_est_view, double *rmse_view) noexcept nogil: cdef Py_ssize_t i, j for i in range(A_view.shape[0]): y_est_view[i] = 0.0 @@ -57,7 +55,7 @@ cdef void _compute_rmse(double [::1, :]A_view, double [::1]y_view, double [::1]x @cython.boundscheck(False) @cython.wraparound(False) -cdef void _compute_nrmse(double [::1, :]A_view, double [::1]y_view, double [::1]x_view, double *y_est_view, double *nrmse_view) nogil: +cdef void _compute_nrmse(double [::1, :]A_view, double [::1]y_view, double [::1]x_view, double *y_est_view, double *nrmse_view) noexcept nogil: cdef double den = 0.0 cdef Py_ssize_t i, j for i in range(A_view.shape[0]): @@ -242,15 +240,33 @@ class StickZeppelinBall( BaseModel ) : self.name = 'Stick-Zeppelin-Ball' self.maps_name = [ ] self.maps_descr = [ ] + self.set() - self.d_par = 1.7E-3 # Parallel diffusivity for the Stick [mm^2/s] - self.d_perp = 0 # Perpendicular diffusivity for the Stick [mm^2/s] - self.d_par_zep = 1.7E-3 # Parallel diffusivity for the Zeppelins [mm^2/s] - self.d_perps_zep = np.array([ 1.19E-3, 0.85E-3, 0.51E-3, 0.17E-3]) # Perpendicular diffusivitie(s) [mm^2/s] - self.d_isos = np.array([ 3.0E-3 ]) # Isotropic diffusivitie(s) [mm^2/s] + def set( + self, + d_par=1.7E-3, + d_perps_zep=np.array([1.19E-3, 0.85E-3, 0.51E-3, 0.17E-3]), + d_isos=np.array([3.0E-3]), + d_par_zep=1.7E-3, + d_perp=0 + ): + ''' + Set the parameters of the Stick-Zeppelin-Ball model. - def set( self, d_par, d_perps_zep, d_isos, d_par_zep=None, d_perp=0 ) : + Parameters + ---------- + d_par : float + Parallel diffusivity for the Stick [mm^2/s] + d_perp : float + Perpendicular diffusivity for the Stick [mm^2/s] + d_par_zep : float + Parallel diffusivity for the Zeppelins [mm^2/s] + d_perps_zep : list of floats + Perpendicular diffusivitie(s) [mm^2/s] + d_isos : list of floats + Isotropic diffusivitie(s) [mm^2/s] + ''' self.d_par = d_par self.d_perp = d_perp if d_par_zep is None: @@ -378,15 +394,30 @@ class CylinderZeppelinBall( BaseModel ) : self.name = 'Cylinder-Zeppelin-Ball' self.maps_name = [ 'v', 'a', 'd' ] self.maps_descr = [ 'Intra-cellular volume fraction', 'Mean axonal diameter', 'Axonal density' ] + self.set() - self.d_par = 0.6E-3 # Parallel diffusivity [mm^2/s] - self.Rs = np.concatenate( ([0.01],np.linspace(0.5,8.0,20)) ) * 1E-6 # Radii of the axons [meters] - self.d_perps = np.array([ 1.19E-3, 0.85E-3, 0.51E-3, 0.17E-3]) # Perpendicular diffusivitie(s) [mm^2/s] - self.d_isos = np.array( [ 2.0E-3 ] ) # Isotropic diffusivitie(s) [mm^2/s] - self.isExvivo = False # Add dot compartment to dictionary (exvivo data) + def set( + self, + d_par=0.6E-3, + Rs=np.concatenate(([0.01], np.linspace(0.5, 8.0, 20))) * 1E-6, + d_perps=np.array([1.19E-3, 0.85E-3, 0.51E-3, 0.17E-3]), + d_isos=np.array([2.0E-3]) + ): + ''' + Set the parameters of the Cylinder-Zeppelin-Ball model. - def set( self, d_par, Rs, d_perps, d_isos ) : + Parameters + ---------- + d_par : float + Parallel diffusivity [mm^2/s] + Rs : list of floats + Radii of the axons [meters] + d_perps : list of floats + Perpendicular diffusivitie(s) [mm^2/s] + d_isos : list of floats + Isotropic diffusivitie(s) [mm^2/s] + ''' self.d_par = d_par self.Rs = np.array(Rs) self.d_perps = np.array(d_perps) @@ -638,19 +669,37 @@ class NODDI( BaseModel ) : self.name = "NODDI" self.maps_name = [ 'NDI', 'ODI', 'FWF' ] self.maps_descr = [ 'Neurite Density Index', 'Orientation Dispersion Index', 'Free Water Fraction' ] + self.set() - self.dPar = 1.7E-3 - self.dIso = 3.0E-3 - self.IC_VFs = np.linspace(0.1,0.99,12) - self.IC_ODs = np.hstack((np.array([0.03, 0.06]),np.linspace(0.09,0.99,10))) - self.isExvivo = False + def set( + self, + dPar=1.7E-33, + dIso=3.0E-3, + IC_VFs=np.linspace(0.1, 0.99, 12), + IC_ODs=np.hstack((np.array([0.03, 0.06]), np.linspace(0.09, 0.99, 10))), + isExvivo=False + ): + ''' + Set the parameters of the NODDI model. - def set( self, dPar, dIso, IC_VFs, IC_ODs, isExvivo ): + Parameters + ---------- + dPar : float + Parallel diffusivity [mm^2/s] + dIso : float + Isotropic diffusivity [mm^2/s] + IC_VFs : list of floats + Intra-cellular volume fractions + IC_ODs : list of floats + Intra-cellular orientation dispersions + isExvivo : bool + Is ex-vivo data + ''' self.dPar = dPar self.dIso = dIso - self.IC_VFs = np.array( IC_VFs ) - self.IC_ODs = np.array( IC_ODs ) + self.IC_VFs = np.array( IC_VFs ) if isinstance(IC_VFs, list) else IC_VFs + self.IC_ODs = np.array( IC_ODs ) if isinstance(IC_ODs, list) else IC_ODs self.isExvivo = isExvivo if isExvivo: self.maps_name.append('dot') @@ -949,44 +998,64 @@ class FreeWater( BaseModel ) : def __init__( self ) : self.id = 'FreeWater' self.name = 'Free-Water' - self.type = 'Human' + self.set() - if self.type == 'Mouse' : - self.maps_name = [ 'FiberVolume', 'FW', 'FW_blood', 'FW_csf' ] - self.maps_descr = [ 'fiber volume fraction', - 'Isotropic free-water volume fraction', - 'FW blood', 'FW csf' ] - # for mouse imaging - self.d_par = 1.0E-3 - self.d_perps = np.linspace(0.15,0.55,10)*1E-3 - self.d_isos = [1.5e-3, 3e-3] - - else : - self.maps_name = [ 'FiberVolume', 'FW' ] - self.maps_descr = [ 'fiber volume fraction', - 'Isotropic free-water volume fraction'] - self.d_par = 1.0E-3 # Parallel diffusivity [mm^2/s] - self.d_perps = np.linspace(0.1,1.0,10)*1E-3 # Parallel diffusivities [mm^2/s] - self.d_isos = [ 2.5E-3 ] # Isotropic diffusivities [mm^2/s] - - - def set( self, d_par, d_perps, d_isos, type ) : - self.d_par = d_par - self.d_perps = d_perps - self.d_isos = d_isos - self.type = type + def set( + self, + d_par=None, + d_perps=None, + d_isos=None, + type='Human' + ): + ''' + Set the parameters of the Free-Water model. + Parameters + ---------- + d_par : float + Parallel diffusivity [mm^2/s] + d_perps : list of floats + Perpendicular diffusivities [mm^2/s] + d_isos : list of floats + Isotropic diffusivities [mm^2/s] + type : str + Type of data ('Human' or 'Mouse') + ''' + self.type = type if self.type == 'Mouse' : self.maps_name = [ 'FiberVolume', 'FW', 'FW_blood', 'FW_csf' ] self.maps_descr = [ 'fiber volume fraction', 'Isotropic free-water volume fraction', 'FW blood', 'FW csf' ] - + if d_par is None: + self.d_par = 1.0E-3 + else: + self.d_par = d_par + if d_perps is None: + self.d_perps = np.linspace(0.15, 0.55, 10) * 1E-3 + else: + self.d_perps = d_perps + if d_isos is None: + self.d_isos = [1.5E-3, 3E-3] + else: + self.d_isos = d_isos else : self.maps_name = [ 'FiberVolume', 'FW' ] self.maps_descr = [ 'fiber volume fraction', 'Isotropic free-water volume fraction'] + if d_par is None: + self.d_par = 1.0E-3 + else: + self.d_par = d_par + if d_perps is None: + self.d_perps = np.linspace(0.1, 1.0, 10) * 1E-3 + else: + self.d_perps = d_perps + if d_isos is None: + self.d_isos = [2.5E-3] + else: + self.d_isos = d_isos PRINT(' %s settings for Freewater elimination... ' % self.type) PRINT(' -iso compartments: ', self.d_isos) @@ -1228,6 +1297,7 @@ class VolumeFractions( BaseModel ) : self.name = 'Volume fractions' self.maps_name = [ ] self.maps_descr = [ ] + self.set() def set( self ) : @@ -1291,14 +1361,30 @@ class SANDI( BaseModel ) : self.name = 'SANDI' self.maps_name = [ 'fsoma', 'fneurite', 'fextra', 'Rsoma', 'Din', 'De' ] self.maps_descr = [ 'Intra-soma volume fraction', 'Intra-neurite volume fraction', 'Extra-cellular volume fraction', 'Apparent soma radius', 'Neurite axial diffusivity', 'Extra-cellular mean diffusivity' ] + self.set() - self.d_is = 3.0E-3 # Intra-soma diffusivity [mm^2/s] - self.Rs = np.linspace(1.0,12.0,5) * 1E-6 # Radii of the soma [meters] - self.d_in = np.linspace(0.25,3.0,5) * 1E-3 # Intra-neurite diffusivitie(s) [mm^2/s] - self.d_isos = np.linspace(0.25,3.0,5) * 1E-3 # Extra-cellular isotropic mean diffusivitie(s) [mm^2/s] + def set( + self, + d_is=3.0E-3, + Rs=np.linspace(1.0, 12.0, 5) * 1E-6, + d_in=np.linspace(0.25, 3.0, 5) * 1E-3, + d_isos=np.linspace(0.25, 3.0, 5) * 1E-3 + ): + ''' + Set the parameters of the SANDI model. - def set( self, d_is, Rs, d_in, d_isos ) : + Parameters + ---------- + d_is : float + Intra-soma diffusivity [mm^2/s] + Rs : list of floats + Radii of the soma [meters] + d_in : list of floats + Intra-neurite diffusivities [mm^2/s] + d_isos : list of floats + Extra-cellular isotropic mean diffusivities [mm^2/s] + ''' self.d_is = d_is self.Rs = np.array(Rs) self.d_in = np.array(d_in) diff --git a/amico/preproc.py b/amico/preproc.py index 74c9dbd..1f64762 100644 --- a/amico/preproc.py +++ b/amico/preproc.py @@ -1,5 +1,3 @@ -from __future__ import print_function - import numpy as np from scipy.optimize import minimize import scipy.special diff --git a/amico/scheme.py b/amico/scheme.py index 36316f4..d2df420 100644 --- a/amico/scheme.py +++ b/amico/scheme.py @@ -1,8 +1,6 @@ -from __future__ import absolute_import, division, print_function - import numpy as np from re import match as re_match -from amico.util import LOG, NOTE, WARNING, ERROR +from amico.util import ERROR from amico.synthesis import _GAMMA class Scheme : diff --git a/amico/util.py b/amico/util.py index 944ad19..b815707 100644 --- a/amico/util.py +++ b/amico/util.py @@ -1,5 +1,3 @@ -from __future__ import absolute_import, division, print_function - import numpy as np import os.path from sys import exit @@ -27,23 +25,23 @@ def get_verbose(): def PRINT( *args, **kwargs ): if __VERBOSE_LEVEL__ >= 2: - print( *args, **kwargs ) + print( *args, **kwargs, flush=True ) def LOG( msg, prefix='' ): if __VERBOSE_LEVEL__ >= 2: - print( prefix+"\033[0;32m%s\033[0m" % msg ) + print( prefix+"\033[0;32m%s\033[0m" % msg, flush=True ) def NOTE( msg, prefix='' ): if __VERBOSE_LEVEL__ == 2: - print( prefix+"\033[0;30;44m[ NOTE ]\033[0;34m %s\033[0m" % msg ) + print( prefix+"\033[0;30;44m[ NOTE ]\033[0;34m %s\033[0m" % msg, flush=True ) def WARNING( msg, prefix='' ): if __VERBOSE_LEVEL__ >= 1: - print( prefix+"\033[0;30;43m[ WARNING ]\033[0;33m %s\033[0m" % msg ) + print( prefix+"\033[0;30;43m[ WARNING ]\033[0;33m %s\033[0m" % msg, flush=True ) def ERROR( msg, prefix='' ): if __VERBOSE_LEVEL__ >= 1: - print( prefix+"\033[0;30;41m[ ERROR ]\033[0;31m %s\033[0m\n" % msg ) + print( prefix+"\033[0;30;41m[ ERROR ]\033[0;31m %s\033[0m\n" % msg, flush=True ) try: from os import EX_USAGE # Only available on UNIX systems exit(EX_USAGE) diff --git a/pyproject.toml b/pyproject.toml index a22bc99..37418f3 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,7 +1,7 @@ [build-system] requires = [ "setuptools>=59.6.0", - "Cython>=3.0.2", + "Cython>=3.0.6", "spams-cython>=1.0.0" ] build-backend = "setuptools.build_meta" diff --git a/setup.cfg b/setup.cfg index d88b63a..0a78da1 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,6 +1,6 @@ [metadata] name = dmri-amico -version = 2.0.1 +version = 2.0.2 url = https://github.com/daducci/AMICO download_url = https://pypi.org/project/dmri-amico project_urls = @@ -34,11 +34,11 @@ keywords = [options] zip_safe = False install_requires = - numpy>=1.19.5 + numpy>=1.19.5, <2.0.0 scipy>=1.5.4 dipy>=1.4.1 threadpoolctl>=3.1.0 - dmri-dicelib>=1.0.1 + dmri-dicelib>=1.0.3 importlib-metadata>=4.8.3; python_version<"3.8" python_requires = >=3.6 packages =