Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true

[{*.{yml,yaml,toml},.cruft.json}]
[*.{yml,yaml,toml}]
indent_size = 2

[Makefile]
Expand Down
13 changes: 13 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# Copy this file to `.env` and fill in your own secrets.
#
# cp .env.example .env
#
# `.env` is gitignored and must NEVER be committed. Only this example file,
# with placeholder values, belongs in version control. If you ever paste a
# real key into a tracked file by mistake, rotate it immediately in the
# provider's dashboard.

# API keys for LLM-based tooling (optional — only if your analysis uses them)
OPENAI_API_KEY="sk-..."
GEMINI_API_KEY="..."
ANTHROPIC_API_KEY="sk-ant-..."
2 changes: 1 addition & 1 deletion .github/ISSUE_TEMPLATE/bug_report.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ assignees: ""
<details> <summary> Versions </summary>

```pytb
# Paste the ouput of tradeseq.__version__ and all relevant versions here
# Paste the output of `session_info2.session_info()` (or your package's __version__) and all relevant versions here
```

</details>
6 changes: 3 additions & 3 deletions .github/pull_request_template.md
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
## Changes

<!-- Please remove section if this PR does change an existing feature -->
<!-- Please remove this section if this PR does not change an existing feature -->

- ...

## Bug fixes

<!-- Please give section if this PR does not fix any bugs -->
<!-- Please remove this section if this PR does not fix any bugs -->

- ...

## New

<!-- Please give section if this PR does not implement a new feature -->
<!-- Please remove this section if this PR does not implement a new feature -->

- ...

Expand Down
3 changes: 2 additions & 1 deletion .github/workflows/lint.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,9 @@ jobs:
fetch-depth: 0
- uses: prefix-dev/setup-pixi@v0.8.0
with:
pixi-version: v0.40.0
pixi-version: v0.60.0
cache: true
frozen: true
- name: Run pre-commit checks
run: pixi run pre-commit run --all-files
- name: Verify notebooks contain no outputs
Expand Down
3 changes: 2 additions & 1 deletion .github/workflows/test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@ jobs:
fetch-depth: 0
- uses: prefix-dev/setup-pixi@v0.8.0
with:
pixi-version: v0.40.0
pixi-version: v0.60.0
cache: true
frozen: true
- name: Run tests
run: pixi run test
12 changes: 0 additions & 12 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ repos:
rev: v2.2.3
hooks:
- id: biome-format
exclude: ^\.cruft\.json$ # inconsistent indentation with cruft - file never to be modified manually.
- repo: https://github.com/tox-dev/pyproject-fmt
rev: v2.6.0
hooks:
Expand All @@ -33,15 +32,4 @@ repos:
args: [--fix=lf]
- id: trailing-whitespace
- id: check-case-conflict
# Check that there are no merge conflicts (could be generated by template sync)
- id: check-merge-conflict
args: [--assume-in-merge]
- repo: local
hooks:
- id: forbid-to-commit
name: Don't commit rej files
entry: |
Cannot commit .rej files. These indicate merge conflicts that arise during automated template updates.
Fix the merge conflicts manually and remove the .rej files.
language: fail
files: '.*\.rej$'
77 changes: 67 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,13 +52,32 @@ The URL depends on your authentication method:

### Step 3: Customize the template

Before installing the environment, update these files with your project details:
The template ships with a placeholder package name (`myanalysis`) and project
name (`analysis-template`). Rename them in one shot with the included script
(stdlib-only, so run it with plain `python` *before* installing the env):

```bash
python scripts/rename_package.py myproject
# or set the Jupyter kernel display name explicitly:
python scripts/rename_package.py myproject --display-name "My Project"
```

This renames `src/myanalysis/` → `src/myproject/` and updates every reference in
`pyproject.toml`, `pixi.toml` (package + workspace + kernel name), `tests/`, and
the notebooks under `analysis/`.

Then finish by hand:

| File | What to change |
|------|----------------|
| `src/myanalysis/` | **Rename this folder** to your project slug (e.g., `src/myproject/`) |
| `pyproject.toml` | Update `name` to match your renamed folder |
| `pixi.toml` | Update `name`, `description`, `authors`, kernel `display-name`, and `myanalysis` → your package name in `[pypi-dependencies]` |
| `pixi.toml` | Update `[workspace]` `description` and `authors` |
| `README.md` | Replace with your own project documentation (Step 6 / later) |

> Doing it manually instead? The placeholder `myanalysis` appears in
> `pyproject.toml`, the `src/myanalysis/` folder name, `pixi.toml`
> (`[pypi-dependencies]`), `tests/test_basic.py`, and the demo notebook; the
> project name `analysis-template` and the kernel `display-name` live in the
> `pixi.toml` `[tasks]` `install-kernel` command. The script handles all of them.

### Step 4: Set up the environment

Expand Down Expand Up @@ -100,7 +119,7 @@ git push

## 📊 Start Your Analysis

- **Demo notebook**: Check out `analysis/demo_scRNA_workflow.ipynb` for a complete scRNA-seq workflow example using scanpy's PBMC 3k dataset.
- **Demo notebook**: Check out `analysis/ML-2026-01-27_demo_scRNA_workflow.ipynb` for a complete scRNA-seq workflow example using scanpy's PBMC 3k dataset.
- **New notebooks**: Copy `analysis/XX-2026-01-27_sample_notebook.ipynb` as a starting point. Follow the naming convention: `[INITIALS]-[YYYY]-[MM]-[DD]_description.ipynb`.
- **Add your data**: Create folders under `data/` and register paths in `src/<your-package>/_constants.py`.
- **Replace this README** with your project documentation once you're set up.
Expand Down Expand Up @@ -213,12 +232,50 @@ pre-commit run --all-files
<details>
<summary><strong>🖥️ GPU notes</strong></summary>

| Platform | PyTorch | JAX |
|----------|---------|-----|
| **macOS** (Apple Silicon) | ✅ MPS acceleration | ❌ CPU only |
| **Linux** (NVIDIA GPU) | ✅ CUDA | ✅ CUDA 12 |
The **default** environment is CPU-only on every platform (on macOS, PyTorch
still uses MPS automatically). This is what `pixi install` and CI use.

GPU acceleration lives in a separate **`gpu`** environment that you opt into
explicitly on a Linux/CUDA machine (e.g. ETH Euler):

```bash
pixi install -e gpu # CUDA 12 build of JAX + rapids-singlecell
pixi run -e gpu install-kernel # register a kernel for the gpu env
pixi shell -e gpu # or activate it interactively
```

| Environment | PyTorch | JAX | rapids-singlecell |
|-------------|---------|-----|-------------------|
| `default` (all platforms) | ✅ (MPS on macOS) | CPU | ❌ |
| `gpu` (Linux + NVIDIA only) | ✅ CUDA | ✅ CUDA 12 | ✅ |

> Keeping the GPU stack out of the default environment means CI and CPU-only
> machines don't try to resolve unusable CUDA wheels. See
> [rapids-singlecell](https://rapids-singlecell.readthedocs.io/).

</details>

<details>
<summary><strong>🔑 Secrets & environment variables</strong></summary>

Store API keys and other secrets in a `.env` file at the repo root. It is
**gitignored** and must never be committed.

```bash
cp .env.example .env # then fill in your real values
```

`.env.example` (tracked, placeholder values only) documents which variables the
project expects. Load them in a notebook or script with, e.g.,
[python-dotenv](https://github.com/theskumar/python-dotenv):

```python
from dotenv import load_dotenv
load_dotenv()
```

The template auto-configures packages per platform. Linux also gets [rapids-singlecell](https://rapids-singlecell.readthedocs.io/) for GPU-accelerated analysis.
If you ever paste a real key into a tracked file, rotate it immediately in the
provider's dashboard — git history is hard to scrub.

</details>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -417,7 +417,9 @@
"id": "31",
"metadata": {},
"source": [
"Now we use the downloaded model for annotation. "
"Now we use the downloaded model for annotation.\n",
"\n",
"⚠️ **Input scale matters.** CellTypist's `Immune_All_High` model expects expression that is **normalized to 10,000 counts per cell and log1p-transformed** (the same transform we applied in the preprocessing step). Annotating data on a different scale (e.g. raw counts, or `sc.pp.scale`-d/z-scored values) silently produces wrong labels. To stay robust we rebuild the expected input from the raw `counts` layer rather than assuming `adata.X` is still in that state."
]
},
{
Expand All @@ -427,9 +429,15 @@
"metadata": {},
"outputs": [],
"source": [
"# Load and annotate\n",
"# Annotate on a fresh copy whose .X is guaranteed to be log1p(normalize_total(1e4)),\n",
"# rebuilt from the raw counts — independent of any later transforms on `adata.X`.\n",
"adata_celltypist = adata.copy()\n",
"adata_celltypist.X = adata_celltypist.layers[\"counts\"].copy()\n",
"sc.pp.normalize_total(adata_celltypist, target_sum=1e4)\n",
"sc.pp.log1p(adata_celltypist)\n",
"\n",
"model = models.Model.load(model=\"Immune_All_High.pkl\")\n",
"predictions = celltypist.annotate(adata, model=model, majority_voting=True)"
"predictions = celltypist.annotate(adata_celltypist, model=model, majority_voting=True)"
]
},
{
Expand Down
3 changes: 2 additions & 1 deletion data/example_dataset/README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# Dataset structure

- `raw`: Raw state of the data we received.
- `processed`: Processed data.
- `processed`: Processed / intermediate data.
- `resources`: Reference data, gene sets, annotations.
- `results`: Any results we compute for this dataset.
Loading
Loading