Skip to content
92 changes: 92 additions & 0 deletions .github/workflows/pypackage_build.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
name: Build and publish python package

on:
push:
tags:
- "*"

# Define permissions needed for the workflow GITHUB_TOKEN
permissions:
contents: read # Allow checkout
packages: write # Allow publishing to GitHub Packages


jobs:
build:
strategy:
matrix:
operating-system: [ macos-latest, ubuntu-latest, windows-latest ]
python-version: [ "3.10", "3.11", "3.12", "3.13" ]

name: Build Python Package (${{ matrix.operating-system }}, Python ${{ matrix.python-version }})
runs-on: ${{ matrix.operating-system }}

steps:
- name: Checkout Code
uses: actions/checkout@v4
with:
ref: ${{ github.ref }}

- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}

- name: Install Hatch
run: pip install hatch

- name: Build distributions
run: hatch build # Uses pyproject.toml to build sdist and wheel into dist/

- name: Upload distributions artifact
uses: actions/upload-artifact@v4 # Action to save artifacts between jobs
with:
name: como-distribution-package-${{ matrix.operating-system }}-${{ matrix.python-version }} # Name for the artifact
path: dist/ # Path to the directory to upload

publish:
strategy:
matrix:
python-version: [ "3.10", "3.11", "3.12", "3.13" ]
operating-system: [ macos-latest, windows-latest, ubuntu-latest ]

name: Publish to GitHub Packages
runs-on: ubuntu-latest
needs: build # Depends on the build job succeeding

# IMPORTANT: Only run the publish job when a tag starting with 'v' is pushed
if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v')


permissions: # Explicit permissions needed for this job
packages: write # Required to write to GitHub Packages registry
contents: read # Needed if accessing repo content (e.g., for download artifact)

steps:
- name: Download distributions artifact
uses: actions/download-artifact@v4 # Action to retrieve artifacts from previous job.
with:
name: como-distribution-package-${{ matrix.operating-system }}-${{ matrix.python-version }}
path: dist/

- name: Set up Python 3.11
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}

- name: Install Twine
run: pip install twine

- name: Publish package to GitHub Packages
env:
# Use __token__ as username and the automatically generated GITHUB_TOKEN as password
TWINE_USERNAME: __token__
TWINE_PASSWORD: ${{ secrets.GITHUB_TOKEN }}
run: |
echo "Uploading to GitHub Packages for repository: ${{ github.repository }}"
# Construct the repository URL dynamically using the repository owner
TWINE_REPOSITORY_URL="https://pypi.pkg.github.com/${{ github.repository_owner }}"
python -m twine upload --verbose --repository-url ${TWINE_REPOSITORY_URL} dist/*



4 changes: 2 additions & 2 deletions main/como/create_context_specific_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@ def _gene_rule_logical(gpr_expression: str, level: int = 0) -> str:
inner_string = inner_string.replace("[", "")
inner_string = inner_string.replace("]", "")

expression_out = f"{gpr_expression[:loc_l]}{inner_string}{gpr_expression[loc_r + 1:]}"
expression_out = f"{gpr_expression[:loc_l]}{inner_string}{gpr_expression[loc_r + 1 :]}"
expression_out = _gene_rule_logical(expression_out, level + 1)

return expression_out
Expand Down Expand Up @@ -384,7 +384,7 @@ def _map_expression_to_reaction(
continue
for gid in gene_ids:
if gid in gene_expressions.index:
rep_val = f' {gene_expressions.at[gid, "active"]} '
rep_val = f" {gene_expressions.at[gid, 'active']} "
else:
rep_val = f" {unknown_val!s} "
gene_reaction_rule = f" {gene_reaction_rule} " # pad white space to prevent gene matches inside floats
Expand Down
3 changes: 1 addition & 2 deletions main/como/rnaseq.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
from functools import partial
from multiprocessing.pool import Pool
from pathlib import Path
from typing import Callable, NamedTuple

Check failure on line 13 in main/como/rnaseq.py

View workflow job for this annotation

GitHub Actions / lint

Ruff (UP035)

main/como/rnaseq.py:13:1: UP035 Import from `collections.abc` instead: `Callable`

import numpy as np
import numpy.typing as npt
Expand Down Expand Up @@ -418,13 +418,12 @@
cores = multiprocessing.cpu_count() - 2
logger.debug(f"Processing {total:,} samples through zFPKM transform using {cores} cores")
logger.debug(
f"Will update every {update_per_step:,} steps as this is approximately "
f"{update_every_percent:.1%} of {total:,}"
f"Will update every {update_per_step:,} steps as this is approximately {update_every_percent:.1%} of {total:,}"
)

with Pool(processes=cores) as pool:
kernel = KernelDensity(kernel="gaussian", bandwidth=bandwidth)
chunksize = int(math.ceil(len(fpkm_df.columns) / (4 * cores)))

Check failure on line 426 in main/como/rnaseq.py

View workflow job for this annotation

GitHub Actions / lint

Ruff (RUF046)

main/como/rnaseq.py:426:21: RUF046 Value being cast to `int` is already an integer
partial_func = partial(_zfpkm_calculation, kernel=kernel, peak_parameters=peak_parameters)
chunk_time = time.time()
start_time = time.time()
Expand Down Expand Up @@ -606,13 +605,13 @@
top_genes: npt.NDArray[bool] = genefilter(boolean_expression, top_func)

# Only keep `entrez_gene_ids` that pass `min_genes`
metric.entrez_gene_ids = [gene for gene, keep in zip(entrez_ids, min_genes) if keep]

Check failure on line 608 in main/como/rnaseq.py

View workflow job for this annotation

GitHub Actions / lint

Ruff (B905)

main/como/rnaseq.py:608:58: B905 `zip()` without an explicit `strict=` parameter
metric.gene_sizes = [gene for gene, keep in zip(gene_size, min_genes) if keep]

Check failure on line 609 in main/como/rnaseq.py

View workflow job for this annotation

GitHub Actions / lint

Ruff (B905)

main/como/rnaseq.py:609:53: B905 `zip()` without an explicit `strict=` parameter
metric.count_matrix = metric.count_matrix.iloc[min_genes, :]
metric.normalization_matrix = metrics[sample].normalization_matrix.iloc[min_genes, :]

keep_top_genes = [gene for gene, keep in zip(entrez_ids, top_genes) if keep]

Check failure on line 613 in main/como/rnaseq.py

View workflow job for this annotation

GitHub Actions / lint

Ruff (B905)

main/como/rnaseq.py:613:50: B905 `zip()` without an explicit `strict=` parameter
metric.high_confidence_entrez_gene_ids = [gene for gene, keep in zip(entrez_ids, keep_top_genes) if keep]

Check failure on line 614 in main/como/rnaseq.py

View workflow job for this annotation

GitHub Actions / lint

Ruff (B905)

main/como/rnaseq.py:614:74: B905 `zip()` without an explicit `strict=` parameter

metrics = calculate_z_score(metrics)

Expand Down
5 changes: 3 additions & 2 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,11 @@ dependencies = [
"loguru>=0.7.2",
"pandas>=1.3.5",
"plotly>=5.24.1",
"scanpy>=1.9.8",
"scanpy>=1.11.1",
"scipy>=1.7.3",
"scikit-learn>=1.5.2",
"setuptools<60.0",
"statsmodels>=0.14",
"openpyxl>=3.1.5",
"aiofiles>=24.1.0",
"aioftp>=0.23.1",
Expand Down Expand Up @@ -49,4 +50,4 @@ packages = ["main/como"]
allow-direct-references = true

[tool.pytest.ini_options]
pythonpath = [ "main/src" ]
pythonpath = [ "main/src" ]
Loading