diff --git a/.github/workflows/test_tutorials.yml b/.github/workflows/test_tutorials.yml new file mode 100644 index 00000000..d12e325c --- /dev/null +++ b/.github/workflows/test_tutorials.yml @@ -0,0 +1,94 @@ +name: Test tutorials + +on: + push: + branches: [main] + pull_request: + branches: [main] + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + test: + runs-on: ubuntu-latest + defaults: + run: + # to fail on error in multiline statements (-e), in pipes (-o pipefail), and on unset variables (-u). + shell: bash -euo pipefail {0} + + env: + NOTEBOOK_PATH: docs/tutorials/notebooks + + strategy: + fail-fast: false + matrix: + notebook: [ + "augur.ipynb", + "cinemaot.ipynb", + "differential_gene_expression.ipynb", + "distances.ipynb", + "distance_tests.ipynb", + "enrichment.ipynb", + "guide_rna_assignment.ipynb", + "milo.ipynb", + "mixscape.ipynb", + "perturbation_space.ipynb", + "sccoda.ipynb", + # "dialogue.ipynb", takes too long + # "tasccoda.ipynb", a pain to get running because of the required QT dependency. The QT action leads to a dead kernel + # also no use cases yet + ] + + steps: + - uses: actions/checkout@v4 + with: + filter: blob:none + fetch-depth: 0 + submodules: "true" + + - name: Cache .pertpy_cache + uses: actions/cache@v4 + with: + path: cache + key: ${{ runner.os }}-pertpy-cache-${{ hashFiles('pertpy/metadata/**') }} + restore-keys: | + ${{ runner.os }}-pertpy-cache + + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: "3.13" + - name: Install R + uses: r-lib/actions/setup-r@v2 + with: + r-version: "4.4.3" + + - name: Cache R packages + id: r-cache + uses: actions/cache@v3 + with: + path: ${{ env.R_LIBS_USER }} + key: ${{ runner.os }}-r-${{ hashFiles('**/pertpy/tools/_milo.py') }} + restore-keys: ${{ runner.os }}-r- + + - name: Install R dependencies + if: steps.r-cache.outputs.cache-hit != 'true' + run: | + mkdir -p ${{ env.R_LIBS_USER }} + Rscript --vanilla -e "install.packages(c('BiocManager', 'statmod'), repos='https://cran.r-project.org'); BiocManager::install('edgeR', lib='${{ env.R_LIBS_USER }}')" + + - name: Install uv + uses: astral-sh/setup-uv@v6 + with: + enable-cache: true + cache-dependency-glob: pyproject.toml + - name: Install dependencies + run: | + uv pip install --system rpy2 decoupler muon + uv pip install --system ${{ matrix.pip-flags }} ".[dev,test,tcoda,de]" + uv pip install --system nbconvert ipykernel + + - name: Run ${{ matrix.notebook }} Notebook + run: jupyter nbconvert --to notebook --execute ${{ env.NOTEBOOK_PATH }}/${{ matrix.notebook }} diff --git a/docs/tutorials/notebooks b/docs/tutorials/notebooks index f7accc3c..2bb24287 160000 --- a/docs/tutorials/notebooks +++ b/docs/tutorials/notebooks @@ -1 +1 @@ -Subproject commit f7accc3ca01d81d4408cf8c57e4f740365a0c514 +Subproject commit 2bb242871bedb95834e100ba2cb5b96d82be6152 diff --git a/pertpy/tools/_coda/_base_coda.py b/pertpy/tools/_coda/_base_coda.py index daf9b622..7b18480c 100644 --- a/pertpy/tools/_coda/_base_coda.py +++ b/pertpy/tools/_coda/_base_coda.py @@ -1472,6 +1472,7 @@ def plot_effects_barplot( # pragma: no cover # noqa: D417 if return_fig and not plot_facets: return plt.gcf() plt.show() + return None @_doc_params(common_plot_args=doc_common_plot_args) @@ -1823,6 +1824,7 @@ def label_point(x, y, val, ax): if return_fig: return plt.gcf() plt.show() + return None @_doc_params(common_plot_args=doc_common_plot_args) @@ -1881,7 +1883,7 @@ def plot_draw_tree( # pragma: no cover # noqa: D417 from ete4.treeview import CircleFace, NodeStyle, TextFace, TreeStyle, faces except ImportError: raise ImportError( - "To use tasccoda please install additional dependencies with `pip install pertpy[coda]`" + "To use tasccoda please install additional dependencies: `pip install pertpy[coda]`" ) from None if isinstance(data, MuData): @@ -1902,8 +1904,8 @@ def my_layout(node): tree.render(save, tree_style=tree_style, units=units, w=figsize[0], h=figsize[1], dpi=dpi) # type: ignore if return_fig: return tree, tree_style + return tree.render("%%inline", tree_style=tree_style, units=units, w=figsize[0], h=figsize[1], dpi=dpi) # type: ignore - return None @_doc_params(common_plot_args=doc_common_plot_args) def plot_draw_effects( # pragma: no cover # noqa: D417 @@ -1969,7 +1971,7 @@ def plot_draw_effects( # pragma: no cover # noqa: D417 from ete4.treeview import CircleFace, NodeStyle, TextFace, TreeStyle, faces except ImportError: raise ImportError( - "To use tasccoda please install additional dependencies as `pip install pertpy[coda]`" + "To use tasccoda please install additional dependencies: `pip install pertpy[coda]`" ) from None if isinstance(data, MuData): @@ -2207,6 +2209,7 @@ def plot_effects_umap( # pragma: no cover # noqa: D417 if return_fig: return fig plt.show() + return None @@ -2325,6 +2328,7 @@ def df2newick(df: pd.DataFrame, levels: list[str], inner_label: bool = True) -> strs = [traverse(df_tax, a, 0, inner_label) for a in alevel] newick = f"({','.join(strs)});" + return newick