Metadata-Version: 2.4
Name: cellmotif2domain
Version: 0.1.0
Summary: Spatial domain detection from cell-type motifs on single-cell spatial maps.
Author: Song Jinsheng
License: MIT
Project-URL: Homepage, https://github.com/your-username/cellmotif2domain
Project-URL: Repository, https://github.com/your-username/cellmotif2domain
Keywords: spatial omics,spatial domains,cellular neighborhoods,motif enrichment,single-cell
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Science/Research
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Topic :: Scientific/Engineering :: Bio-Informatics
Requires-Python: >=3.9
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: numpy>=1.23
Requires-Dist: pandas>=1.5
Requires-Dist: scipy>=1.9
Requires-Dist: scikit-learn>=1.2
Requires-Dist: matplotlib>=3.6
Requires-Dist: numba>=0.57
Requires-Dist: threadpoolctl>=3.1
Dynamic: license-file

# Cellmotif2domain

Cellmotif2domain identifies spatial domains from single-cell spatial maps using recurrent cell-type motifs. It only requires spatial coordinates and cell-type labels. The method builds a sample-wise Delaunay graph, extracts graph-constrained cell-type motifs, calculates cell-level motif enrichment against a sample-specific null model, and clusters the resulting cell-by-motif matrix into spatial domains.

The package is designed for single-cell spatial proteomics, spatial transcriptomics after cell typing, and other imaging-based spatial omics datasets.

## Installation

Install from a local checkout:

```bash
cd cellmotif2domain
pip install .
```

For editable development:

```bash
cd cellmotif2domain
pip install -e .
```

Core dependencies are `numpy`, `pandas`, `scipy`, `scikit-learn`, `matplotlib`, `numba`, and `threadpoolctl`.

## Input Data

Cellmotif2domain expects one cell-level table in CSV, CSV.GZ, TSV, TSV.GZ or Parquet format. Each row is one cell.

Required columns:

| Column | Meaning |
| --- | --- |
| `sample_id` | Tissue section, FOV, core, or sample identifier. Graphs are built separately for each sample. |
| `cell_id` | Unique cell identifier. |
| `x` | Spatial x coordinate. |
| `y` | Spatial y coordinate. |
| `cell_type` | Cell-type label used for motif construction. |

Optional columns:

| Column | Meaning |
| --- | --- |
| `dataset_id` | Dataset or cohort name. |
| `true_domain` | Reference spatial-domain annotation, if available. |
| `true_domain_id` | Numeric reference-domain annotation, if available. |

Example:

```csv
sample_id,cell_id,x,y,cell_type
sample_1,cell_001,0.0,0.0,Tumor
sample_1,cell_002,1.0,0.1,Tumor
sample_1,cell_003,0.2,1.1,Stroma
sample_1,cell_004,1.2,1.0,T_cell
sample_2,cell_001,0.1,0.2,B_cell
```

If your columns have different names, pass them with `--x-col`, `--y-col`, `--sample-col`, `--cell-id-col`, and `--celltype-col`.

## Quick Start

Run motif feature construction and domain calling in one command:

```bash
cellmotif2domain run \
  --cell-table cells.csv \
  --sample-col sample_id \
  --cell-id-col cell_id \
  --x-col x \
  --y-col y \
  --celltype-col cell_type \
  --n-domains 8 \
  --output-dir results/cellmotif2domain_k8 \
  --walk-length 10 \
  --walks-per-cell 100 \
  --n-jobs 16 \
  --export-csv
```

The `--export-csv` flag writes the final domain table and cell-by-motif matrix as CSV.GZ files for downstream analysis.

## Two-Step Usage

For exploring multiple `k` values, run motif construction once, then run domain calling repeatedly:

```bash
cellmotif2domain motifwalk \
  --cell-table cells.csv \
  --output-dir results/motifwalk_L10 \
  --walk-length 10 \
  --walks-per-cell 100 \
  --motif-min-len 3 \
  --motif-max-len 5 \
  --max-selected-motifs 2000 \
  --n-jobs 16 \
  --export-csv

cellmotif2domain domaincall \
  --motif-dir results/motifwalk_L10 \
  --n-domains 8 \
  --export-csv

cellmotif2domain domaincall \
  --motif-dir results/motifwalk_L10 \
  --n-domains 12 \
  --export-csv
```

This is usually faster than rerunning the full workflow for every candidate `k`.

## Python API

```python
from cellmotif2domain import Cellmotif2domain, MotifWalk, DomainCall
from cellmotif2domain import export_cell_by_motif_csv, export_domains_csv

domains = Cellmotif2domain(
    "cells.csv",
    n_domains=8,
    x_col="x",
    y_col="y",
    celltype_col="cell_type",
    sample_col="sample_id",
    cell_id_col="cell_id",
    output_dir="results/cellmotif2domain_k8",
    walk_length=10,
    walks_per_cell=100,
    motif_min_len=3,
    motif_max_len=5,
    max_selected_motifs=2000,
    enrichment=True,
    n_jobs=16,
    random_seed=42,
)

export_domains_csv("results/cellmotif2domain_k8", n_domains=8)
export_cell_by_motif_csv("results/cellmotif2domain_k8")
```

The older internal name `SpaMotifDomain` is kept as an alias for compatibility, but new analyses should use `Cellmotif2domain`.

## Main Parameters

| Parameter | Default | Meaning |
| --- | ---: | --- |
| `--n-domains` | required | Number of spatial domains to call. |
| `--walk-length` | `10` | Length of graph-constrained random walks. |
| `--walks-per-cell` | `100` | Number of seeded walks requested per cell. |
| `--motif-min-len` | `3` | Minimum cell-type motif length. |
| `--motif-max-len` | `walk_length / 2`, capped at `10` | Maximum motif length. |
| `--max-selected-motifs` | `2000` | Number of selected motif features used for clustering. |
| `--enrichment` | `true` | Use analytic null-model log2 enrichment instead of raw log2 counts. |
| `--pca-components` | `30` | PCA dimensions before clustering. |
| `--n-jobs` | auto | CPU threads for motif counting. |
| `--save-walks` | off | Save raw walk paths. This can be large. |

Recommended starting point: `walk_length=10`, `walks_per_cell=100`, `motif_min_len=3`, `motif_max_len=5`, `enrichment=true`, and `max_selected_motifs=2000`.

## Output Files

For an output directory such as `results/cellmotif2domain_k8`, the main files are:

| File | Description |
| --- | --- |
| `metadata/spatial_cells.tsv.gz` | Cleaned input cell table with encoded cell types. |
| `outputs/graphs/spatial_delaunay_neighbors.npy` | Delaunay graph neighbor array. |
| `outputs/graphs/spatial_delaunay_graph_summary.tsv` | Per-sample graph summary. |
| `outputs/motifs/motif_counts_L*_L*.tsv.gz` | Global candidate motif counts. |
| `outputs/motifs/selected_motif_features.tsv` | Selected motifs with motif sequence and count/prevalence metadata. |
| `outputs/motifs/selected_motif_analytic_background.tsv` | Observed/expected motif counts under the analytic null model. |
| `outputs/features/cell_selected_motif_counts.npz` | Sparse cell-by-motif count matrix. |
| `outputs/features/cell_selected_motif_log2_enrichment.npz` | Sparse cell-by-motif log2 enrichment matrix. |
| `outputs/features/cell_by_motif_matrix.csv.gz` | CSV export of the selected cell-by-motif matrix when `--export-csv` is used. |
| `outputs/domains/cellmotif2domain_domains_k*.tsv.gz` | Domain assignments per cell. |
| `outputs/domains/cellmotif2domain_domains_k*.csv.gz` | CSV export of domain assignments when `--export-csv` is used. |
| `outputs/figures/cellmotif2domain_smoothed_domain_k*.pdf` | Spatial domain map as editable PDF. |

The domain table contains:

| Column | Meaning |
| --- | --- |
| `cell_id`, `sample_id`, `x`, `y`, `cell_type` | Cell metadata. |
| `cellmotif2domain_raw` | Cluster label before spatial smoothing. |
| `cellmotif2domain_smoothed` | Cluster label after one round of Delaunay-neighbor majority smoothing. |

The cell-by-motif CSV uses columns named like:

```text
motif_0001|B_cell-T_cell-Macrophage
```

Values are log2 enrichment scores when `--enrichment true` is used. A value above `0` means the motif is enriched relative to the sample-specific null expectation.

## Algorithm Summary

1. Build a Delaunay triangulation graph independently for each `sample_id`.
2. Start graph-constrained self-avoiding random walks from each cell.
3. Extract cell-type motif windows from each walk.
4. Canonicalize motif direction so a motif and its reverse are treated as the same motif.
5. Count motifs at the cell level.
6. Estimate expected motif counts from sample-wise cell-type frequencies.
7. Compute a sparse cell-by-motif log2 enrichment matrix.
8. Reduce the motif matrix by PCA.
9. Cluster cells with diagonal Gaussian mixture modeling and apply one round of spatial smoothing.

## GitHub Release Checklist

Before pushing this package to GitHub, keep raw data and large outputs out of the repository:

```bash
cd cellmotif2domain
git init
git add .
git commit -m "Initial release of Cellmotif2domain"
git branch -M main
git remote add origin git@github.com:YOUR_USERNAME/cellmotif2domain.git
git push -u origin main
```

Do not commit patient-level raw data, large matrices, private logs, tokens, or local result folders.

## PyPI Packaging

Build a source distribution and wheel:

```bash
cd cellmotif2domain
python -m pip install build twine
python -m build
python -m twine check dist/*
```

Upload to TestPyPI first:

```bash
python -m twine upload --repository testpypi dist/*
```

Then install-test in a clean environment:

```bash
pip install -i https://test.pypi.org/simple/ cellmotif2domain
```

GitHub and PyPI use tokens or SSH keys; do not enter or share your GitHub password in scripts.
