diff --git a/.conda/bin/build b/.conda/bin/build index 1967ddb7..b40f4f5b 100755 --- a/.conda/bin/build +++ b/.conda/bin/build @@ -8,6 +8,12 @@ then python_version=3.7 fi +out_dir=$2 +if [ -z "$out_dir" ] +then + out_dir=conda_build_out_dir/ +fi + export BRAINIAK_HOME=$DIR/../../ # See run-tests.sh @@ -28,5 +34,5 @@ then variants="{'CONDA_BUILD_SYSROOT': ['${sdk_path}']}" fi -"$CONDA_HOME"/bin/conda build --python=$python_version \ +"$CONDA_HOME"/bin/conda build --output-folder $out_dir --python=$python_version \ "$variants_prefix" "$variants" "$DIR"/.. diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 710ed5da..897d8fed 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -1,4 +1,10 @@ -on: [pull_request, push] +on: + pull_request: + push: + release: + types: + - published + concurrency: group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} @@ -38,17 +44,79 @@ jobs: runs-on: ${{ matrix.os }} strategy: matrix: - os: [ubuntu-20.04, macos-latest] - python-version: [3.8] + os: [ubuntu-latest, macos-latest] + python-version: ['3.8', '3.9', '3.10'] steps: - uses: actions/checkout@v2 - - uses: mamba-org/setup-micromamba@v1 + - name: Setup micromamba and boa + uses: mamba-org/setup-micromamba@v1 with: environment-name: test-env create-args: >- python=${{ matrix.python-version }} boa - - run: | + - name: Build and test package + id: build-package + run: | export CONDA_HOME=$CONDA conda install conda-build - .conda/bin/build ${{ matrix.python-version }} + out_dir="${{ matrix.os }}-build" + .conda/bin/build ${{ matrix.python-version }} $out_dir + echo "PACKAGE_PATH=${out_dir}" >> "$GITHUB_OUTPUT" + + - uses: actions/upload-artifact@v3 + with: + path: ${{ steps.build-package.outputs.PACKAGE_PATH }} + + publish_conda: + needs: [conda] + name: Publish to Anaconda + environment: anaconda + permissions: + id-token: write + runs-on: ubuntu-latest + if: github.event_name == 'release' && github.event.action == 'published' + + steps: + - uses: actions/download-artifact@v3 + with: + name: artifact + path: ${{ steps.build-package.outputs.PACKAGE_PATH }} + + - name: List files in artifact + run: find ${{ steps.build-package.outputs.PACKAGE_PATH }} -type f -name "*.tar.bz2" + + - name: Upload to Anaconda + if: github.event_name == 'release' && github.event.action == 'published' + run: | + export ANACONDA_API_TOKEN=${{ secrets.ANACONDA_TOKEN }} + find ${{ steps.build-package.outputs.PACKAGE_PATH }} -type f -name "*.tar.bz2" -exec echo "anaconda upload {}" \; + + dist: + name: Distribution build + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - uses: hynek/build-and-inspect-python-package@v1 + + publish_pypi: + name: Publish to PyPI + needs: [dist] + environment: + name: pypi + url: https://pypi.org/p/brainiak + permissions: + id-token: write + runs-on: ubuntu-latest + if: github.event_name == 'release' && github.event.action == 'published' + steps: + - uses: actions/download-artifact@v3 + with: + name: Packages + path: dist + + - uses: pypa/gh-action-pypi-publish@release/v1 \ No newline at end of file diff --git a/brainiak/reprsimil/brsa.py b/brainiak/reprsimil/brsa.py index eadd7ec3..1d17500b 100755 --- a/brainiak/reprsimil/brsa.py +++ b/brainiak/reprsimil/brsa.py @@ -2322,7 +2322,8 @@ def _loglike_AR1_diagV_fitU(self, param, XTX, XTDX, XTFX, YTY_diag, - np.dot(invX0TAX0_X0TAX_ele.T, dX0TAY_drho1[:, i_v]) \ - np.dot(dXTAX0_drho1[i_v, :, :], invX0TAX0_X0TAY_ele) \ + np.linalg.multi_dot([invX0TAX0_X0TAX_ele.T, - dX0TAX0_drho1[i_v, :, :], invX0TAX0_X0TAY_ele]) + dX0TAX0_drho1[i_v, :, :], + invX0TAX0_X0TAY_ele]) dYTAcorrY_drho1_ele = dYTAY_drho1[i_v] \ - np.dot(dX0TAY_drho1[:, i_v], invX0TAX0_X0TAY_ele) * 2\ + np.dot(np.dot(invX0TAX0_X0TAY_ele, dX0TAX0_drho1[i_v, :, :]), @@ -2332,7 +2333,8 @@ def _loglike_AR1_diagV_fitU(self, param, XTX, XTDX, XTFX, YTY_diag, - np.einsum('ij,ij', X0TAX0_i[i_v, :, :], dX0TAX0_drho1[i_v, :, :]) * 0.5 - np.einsum('ij,ij', LAMBDA[i_v, :, :], - np.linalg.multi_dot([L.T, dXTAcorrX_drho1_ele, L])) + np.linalg.multi_dot([L.T, + dXTAcorrX_drho1_ele, L])) * (SNR2[i_v] * 0.5) - dYTAcorrY_drho1_ele * 0.5 / sigma2[i_v] + SNR2[i_v] / sigma2[i_v] @@ -2340,8 +2342,8 @@ def _loglike_AR1_diagV_fitU(self, param, XTX, XTDX, XTFX, YTY_diag, YTAcorrXL_LAMBDA_LT[i_v, :]) - (0.5 * SNR2[i_v]**2 / sigma2[i_v]) * np.linalg.multi_dot([YTAcorrXL_LAMBDA_LT[i_v, :], - dXTAcorrX_drho1_ele, - YTAcorrXL_LAMBDA_LT[i_v, :]])) + dXTAcorrX_drho1_ele, + YTAcorrXL_LAMBDA_LT[i_v, :]])) deriv = np.empty(np.size(param)) deriv[idx_param_fitU['Cholesky']] = deriv_L[l_idx] @@ -2478,7 +2480,7 @@ def _loglike_AR1_diagV_fitV(self, param, deriv_c_space = \ (np.linalg.multi_dot([invK_tilde_log_SNR, dK_tilde_dl2_space, - invK_tilde_log_SNR]) / tau2 / 2.0 + invK_tilde_log_SNR]) / tau2 / 2.0 - np.sum(inv_K_tilde * dK_tilde_dl2_space) / 2.0)\ * dl2_dc_space @@ -2492,8 +2494,9 @@ def _loglike_AR1_diagV_fitV(self, param, dK_tilde_dl2_inten = inten_dist2 * K_major \ / 2.0 / l2_inten**2 deriv_c_inten = \ - (np.linalg.multi_dot([invK_tilde_log_SNR, dK_tilde_dl2_inten, - invK_tilde_log_SNR]) / tau2 / 2.0 + (np.linalg.multi_dot([invK_tilde_log_SNR, + dK_tilde_dl2_inten, + invK_tilde_log_SNR]) / tau2 / 2.0 - np.sum(inv_K_tilde * dK_tilde_dl2_inten) / 2.0)\ * dl2_dc_inten # Prior on the length scale @@ -2573,7 +2576,7 @@ def _loglike_AR1_singpara(self, param, XTX, XTDX, XTFX, YTY_diag, deriv_L = np.dot(XTAcorrY, LAMBDA_LTXTAcorrY.T) / sigma2 \ - np.linalg.multi_dot([XTAcorrXL, LAMBDA_LTXTAcorrY, - LAMBDA_LTXTAcorrY.T]) / sigma2 \ + LAMBDA_LTXTAcorrY.T]) / sigma2 \ - np.linalg.solve(LAMBDA_i, XTAcorrXL.T).T * n_V # These terms are used to construct derivative to a1. @@ -2586,7 +2589,7 @@ def _loglike_AR1_singpara(self, param, XTX, XTDX, XTFX, YTY_diag, dXTAcorrX_drho1 = dXTAX_drho1 - dXTAX0_drho1_invX0TAX0_X0TAX \ - dXTAX0_drho1_invX0TAX0_X0TAX.T \ + np.linalg.multi_dot([invX0TAX0_X0TAX.T, dX0TAX0_drho1, - invX0TAX0_X0TAX]) + invX0TAX0_X0TAX]) dLTXTAcorrXL_drho1 = np.linalg.multi_dot([L.T, dXTAcorrX_drho1, L]) dYTAY_drho1 = - YTDY_diag + 2 * rho1 * YTFY_diag @@ -2604,7 +2607,7 @@ def _loglike_AR1_singpara(self, param, XTX, XTDX, XTFX, YTY_diag, - np.dot(dXTAX0_drho1, invX0TAX0_X0TAY) \ - np.dot(invX0TAX0_X0TAX.T, dX0TAY_drho1) \ + np.linalg.multi_dot([invX0TAX0_X0TAX.T, dX0TAX0_drho1, - invX0TAX0_X0TAY]) + invX0TAX0_X0TAY]) deriv_a1 = 2.0 / (np.pi * (1 + a1**2)) \ * (n_V * (- n_run * rho1 / (1 - rho1**2) @@ -2673,8 +2676,9 @@ def _loglike_AR1_null(self, param, YTY_diag, YTDY_diag, YTFY_diag, # preparation for the variable below dYTAcorrY_drho1_ele = dYTAY_drho1[i_v] \ - np.dot(dX0TAY_drho1[:, i_v], invX0TAX0_X0TAY_ele) * 2\ - + np.linalg.multi_dot([invX0TAX0_X0TAY_ele, dX0TAX0_drho1[i_v, :, :], - invX0TAX0_X0TAY_ele]) + + np.linalg.multi_dot([invX0TAX0_X0TAY_ele, + dX0TAX0_drho1[i_v, :, :], + invX0TAX0_X0TAY_ele]) deriv_a1[i_v] = 2 / np.pi / (1 + a1[i_v]**2) \ * (- n_run * rho1[i_v] / (1 - rho1[i_v]**2) - np.einsum('ij,ij', X0TAX0_i[i_v, :, :], @@ -3368,10 +3372,10 @@ def _precompute_ar1_quad_forms_marginalized( for i_r in range(np.size(rho1)): XTAcorrX[i_r, :, :] -= \ np.linalg.multi_dot([XTAX0[i_r, :, :], X0TAX0_i[i_r, :, :], - XTAX0[i_r, :, :].T]) + XTAX0[i_r, :, :].T]) XTAcorrY[i_r, :, :] -= np.linalg.multi_dot([XTAX0[i_r, :, :], - X0TAX0_i[i_r, :, :], - X0TAY[i_r, :, :]]) + X0TAX0_i[i_r, :, :], + X0TAY[i_r, :, :]]) YTAcorrY_diag[i_r, :] -= np.sum( X0TAY[i_r, :, :] * np.dot(X0TAX0_i[i_r, :, :], X0TAY[i_r, :, :]), axis=0) @@ -3637,8 +3641,8 @@ def _fit_RSA_marginalized(self, X, Y, X_base, X0TAX0_i[subj][grid, :, :], (X0TAY[subj][grid, :, :] - np.linalg.multi_dot([XTAX0[subj][grid, :, :].T, - L_LAMBDA_LT[grid, :, :], - sXTAcorrY[subj][grid, :, :]]) + L_LAMBDA_LT[grid, :, :], + sXTAcorrY[subj][grid, :, :]]) * all_SNR_grids[grid])) if np.max(np.abs(param_change)) < self.tol: logger.info('The change of parameters is smaller than ' @@ -3814,7 +3818,8 @@ def _raw_loglike_grids(self, L, s2XTAcorrX, YTAcorrY_diag, LAMBDA_i = np.empty((n_grid, rank, rank)) for grid in np.arange(n_grid): LAMBDA_i[grid, :, :] = np.linalg.multi_dot([L.T, - s2XTAcorrX[grid, :, :], L]) + s2XTAcorrX[grid, :, :], + L]) LAMBDA_i += np.identity(rank) # dimension: n_grid * rank * rank Chol_LAMBDA_i = np.linalg.cholesky(LAMBDA_i)