シングルセル・マルチオミクス(single-cell multiomics/scRNA-seq と scATAC-seq の統合解析)は、まず2つのモダリティを1つのデータ構造にまとめるところから始まります。この記事では、単独解析で使う AnnData と、それを束ねる MuData / muon を、実際のコードとともに理解します。
1. AnnData ─ 1モダリティの入れ物
マルチオミクスも、土台は単独解析と同じ AnnData です。AnnData は1つのモダリティ(例:RNA)を1つのオブジェクトに収めた入れ物で、データ行列とそのメタデータをまとめて持ちます(Scanpy の基盤データ構造;Wolf et al., Genome Biol., 2018)。
.X=データ行列(cells × features)。.obs=細胞ごとのメタデータ(行)。.var=特徴ごとのメタデータ(列)。.layers=生カウントなど別の行列を同じ形で保持。.obsm=UMAP / PCA などの埋め込み。.uns=その他の情報。
実際に中身を確かめます。
python
import scanpy as sc
# 1モダリティ = AnnData を読み込む
adata = sc.read_h5ad("rna.h5ad")
adata.shape # (n_cells, n_genes)
adata.obs.head() # 細胞ごとのメタデータ(行)
adata.var.head() # 特徴(遺伝子)ごとのメタデータ(列)
adata.layers["counts"] # 生カウントなどの別行列
adata.obsm["X_umap"] # 埋め込み(UMAP など)
この6つの引き出し(.X/.obs/.var/.layers/.obsm/.uns)を押さえれば AnnData は難しくありません。マルチオミクスでは、これを2つ束ねます。
2. MuData ─ 2つのモダリティを束ねる
MuData は、複数の AnnData を1つに束ねるコンテナです(Bredikhin et al., Genome Biol., 2022)。各モダリティは mod[‘rna’]/mod[‘atac’] として中に入り、全体の細胞情報は MuData 自身の .obs が持ちます。
各モダリティは .mod[‘名前’] の中の AnnData として保持されます。全体(グローバル)の .obs が細胞をまとめ、どの細胞がどのモダリティにあるかは .obsm の対応マップ(モダリティごとの真偽値)で管理されます。ペアならこのマップで細胞がそろい、非ペアなら別々の集団を並べて持てます。
作成とアクセスはこうです。
python
from muon import MuData
# 2つの AnnData を1つに束ねる
mdata = MuData({"rna": adata_rna, "atac": adata_atac})
mdata # MuData(2モダリティ)
mdata.mod["rna"] # RNA 側の AnnData
mdata["atac"] # ATAC 側(省略記法)
mdata.obs.head() # 全体(グローバル)の obs
3. データを読み込む ─ ペア(10x Multiome)と非ペア
ペア(10x Multiome)は、muon の読み込み関数を使うと、RNA と ATAC を含む MuData がそのまま得られます。この関数は内部で Scanpy の 10x リーダーを呼び、ピークのゲノム区間(interval)やフラグメント情報も補います。
python
import muon as mu
# 10x Multiome(ペア)→ "rna" と "atac" を含む MuData
mdata = mu.read_10x_h5("filtered_feature_bc_matrix.h5")
mdata["rna"].shape # (n_cells, n_genes)
mdata["atac"].shape # (n_cells, n_peaks)
mdata["atac"].var["interval"].head() # ピークのゲノム区間
一方 非ペアは、別々に用意した2つの AnnData を MuData に束ねます。細胞バーコードは共有されないため、行(細胞)は対応しません。
python
from muon import MuData
# 非ペア:別々に測った2つの AnnData(細胞は対応しない)
mdata = MuData({"rna": adata_rna, "atac": adata_atac})
mdata["rna"].obs_names[:3] # RNA 側の細胞バーコード
mdata["atac"].obs_names[:3] # ATAC 側は別のバーコード
ペアは同じ細胞が両モダリティに並ぶので、全体の .obs が両方に対応します(合同 QC ができます)。非ペアは別々の細胞集団なので .obs は共有されません。この違いが、次の同期の扱いに効いてきます。
4. モダリティ間の同期 ─ obs 軸と update / intersect_obs
MuData を使ううえで最も間違えやすいのが、モダリティ側で細胞を削ったあとの同期です。片方の AnnData をフィルタしても、全体(グローバル)の .obs は自動では縮みません。
python
import scanpy as sc
import muon as mu
# モダリティ側でフィルタしたら、全体の obs を同期
sc.pp.filter_cells(mdata["rna"], min_genes=200)
mdata.update()
# ペアなら、両モダリティに共通する細胞だけを残す
mu.pp.intersect_obs(mdata)
モダリティ側で filter_cells などを実行したら、mdata.update() を呼んで全体の .obs を同期します。ペアデータで両モダリティに共通する細胞だけを残したいときは mu.pp.intersect_obs(mdata) を使います。同期を忘れると、後段で行数(obs)の不一致エラーが出ます。
5. 生カウントの置き場所(.layers)
前処理ハブで述べたとおり、MultiVI や scVI は生カウントを入力に取ります(Lopez et al., Nat. Methods, 2018/Ashuach et al., Nat. Methods, 2023)。正規化で .X を上書きする前に、生カウントを .layers に退避しておきます。
python
# 正規化の前に、生カウントを別レイヤーへ退避
adata = mdata["rna"]
adata.layers["counts"] = adata.X.copy()
# 以降 .X は可視化用に正規化してよい(生は .layers に残る)
sc.pp.normalize_total(adata, target_sum=1e4)
sc.pp.log1p(adata)
normalize_total や log1p は .X を書き換えます。先に .layers[‘counts’] へ生カウントをコピーしておけば、可視化用の正規化と、モデル入力用の生カウントを1つのオブジェクトで両立できます。ATAC 側も同様に、生のピークカウントを残します。
6. 保存と読み込み(.h5mu)
整えた MuData は、.h5mu 形式で保存できます。.h5ad と同じ HDF5 ベースで、階層的に各モダリティを格納します。1モダリティだけを直接読み書きすることもできます。
python
import mudata as md
# 保存(.h5mu)
mdata.write("multiome.h5mu")
# 読み込み
mdata = md.read("multiome.h5mu")
adata_rna = md.read("multiome.h5mu/rna") # 1モダリティだけ読む
これで、前処理を始める土台(RNA・ATAC を束ねた MuData)が整いました。次回は、この上で RNA 側の前処理を具体的に進めます。
まとめ
- 土台は AnnData(1モダリティ)と、それを束ねる MuData(複数モダリティ)。
- AnnData の引き出しは .X/.obs/.var/.layers/.obsm/.uns。MuData は各モダリティを .mod に持ち、全体の .obs でまとめる。
- ペアは mu.read_10x_h5 で1発、非ペアは2つの AnnData を MuData に束ねる。ペアは細胞がそろい、非ペアはそろわない。
- モダリティ側でフィルタしたら mdata.update()/共通細胞は mu.pp.intersect_obs。同期忘れは obs 不一致エラーの原因。
- 生カウントは正規化前に .layers[‘counts’] へ退避(MultiVI / scVI 用)。保存は .h5mu。
関連記事
- 📖 マルチオミクス前処理の全体像(前の記事) … 前処理の地図
- 📖 AnnData のデータ構造 … 単独解析での AnnData
- 📖 scvi-tools の全体像 … MultiVI / scVI の土台
- 📖 scRNA-seq 前処理の全体像 … RNA 側の詳細
- 📖 scATAC-seq 解析の全体像 … ATAC 側の詳細
参考文献
- Bredikhin, D., Kats, I., & Stegle, O. (2022). MUON: multimodal omics analysis framework. Genome Biology, 23, 42. doi:10.1186/s13059-021-02577-8
- Wolf, F. A., Angerer, P., & Theis, F. J. (2018). SCANPY: large-scale single-cell gene expression data analysis. Genome Biology, 19, 15. doi:10.1186/s13059-017-1382-0
- Lopez, R., Regier, J., Cole, M. B., Jordan, M. I., & Yosef, N. (2018). Deep generative modeling for single-cell transcriptomics. Nature Methods, 15(12), 1053–1058. doi:10.1038/s41592-018-0229-2
- Ashuach, T., Gabitto, M. I., Koodli, R. V., et al. (2023). MultiVI: deep generative model for the integration of multimodal data. Nature Methods, 20(8), 1222–1231. doi:10.1038/s41592-023-01909-9


コメント