genvarloader について
GenVarLoaderは、参照配列とバリアントから個人別ハプロタイプを再構築し、機能ゲノムトラックを再配置するPythonライブラリです。可変長出力に対応し、複数のバリアント保存形式を扱えます。
主な機能
- 01個人別ハプロタイプの再構築
- 02BigWig・テーブルトラックの再配置
- 03BCF、PGEN、SVAR、SVAR2への対応
- 04既存データセットへのトラック追加
- 05可変長ゲノム出力の読み取り
活用シーン
- 01指定領域とサンプルのゲノムデータセット作成
- 02挿入・欠失を反映したハプロタイプの読み取り
- 03複数データセットでのバリアントソースの再利用
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ mcvickerlab/ genvarloader --skill genvarloaderインストール後、Claude Code で/genvarloaderを入力して読み込まれたか確認します。
詳細
GenVarLoader 公開 API
GenVarLoader(gvl)は、参照配列 + バリアント + BigWig/Table トラックから、個人ごとのハプロタイプを再構築し、機能ゲノミクストラックをオンザフライで再アラインメントします。個人ごとのゲノムをディスクに書き出すことはありません。可変長の出力が常態です(インデルにより長さは領域およびサンプルに依存します)。
このスキルは、ポインタを多用した概要です。シンボル名は、権威ある docstring やソースの場所へリンクしています。
エンドツーエンドの流れ
import genvarloader as gvl
# 1. Preprocess variants outside Python (see "Variant preprocessing")
# 2. Write the dataset
gvl.write(
path="ds.gvl",
bed="rois.bed",
variants="normed.bcf", # or .pgen, or .svar directory
tracks=[gvl.BigWigs.from_table("signal", "bw_table.tsv")],
max_jitter=128,
)
# 3. Open and configure (chainable fluent API)
ds = (
gvl.Dataset
.open("ds.gvl", reference="ref.fa")
.with_seqs("haplotypes")
.with_tracks(["signal"])
.with_insertion_fill(gvl.Repeat5pNormalized())
.with_len(2048) # or "ragged" / "variable"
.with_settings(jitter=32, deterministic=False)
)
# 4. Eager indexing: dataset[region_idx, sample_idx]
batch = ds[0:8, :] # shape depends on with_* state — see "Output shapes"
バリアント前処理の要件
gvl.write に渡すバリアントは、必ず左寄せ、バイアレリック、原子的(MNP や複合 MNP-インデルを含まない)であり、シンボリック(<DEL>、<INS>、…)およびブレイクエンドの ALT アレルを含まないものでなければなりません。gvl はすべての ALT をリテラルのハプロタイプ配列へ展開するため、シンボリックやブレイクエンドのレコードを再構築できません。VCF、PGEN、SVAR のいずれの入力でも、これらが存在する場合、gvl.write は ValueError を発生させます(マルチアレリック、シンボリック、ブレイクエンドのバリアントのクラス別件数付き)。VCF はインデックス化されている必要があります。
# VCF/BCF
bcftools norm -f ref.fa \
-a --atom-overlaps . \
-m -any --multi-overlaps . \
-O b -o normed.bcf in.vcf.gz
bcftools index normed.bcf
# PGEN
plink2 --make-bpgen --pfile in --out tmp
plink2 --make-pgen --normalize --ref-from-fa --fa ref.fa --bpfile tmp --out normed
正規のレシピと BED/BigWig テーブルのレイアウトについては docs/source/write.md を参照してください。
SVAR と BCF/PGEN のどちらを使うか
.svar は(genoray による)スパースな列指向のバリアントアーカイブです。BCF や PGEN とまったく同じように gvl.write(variants="x.svar") に渡してください。結果として得られるデータセットは、バリアントごとの配列を重複させる代わりにバックリファレンスを保存します。
SVAR を使うのは次の場合です:
- 読み取り時のアレル頻度フィルタリングが必要な場合(
Dataset.open(min_af=..., max_af=...)は.svarのみでサポートされます。.svar2をバックエンドとするデータセットではNotImplementedErrorが発生します)。 - 多くのデータセットが同じバリアントソースを共有する場合 — SVAR は
variant_idxs.npy/dosages.npy/variants.arrowを各.gvlディレクトリへ重複させることを避けられます。 - 集団規模で作業しており、コンパクトなオンディスクのバリアントストレージを求める場合。
BCF/PGEN を直接使うのは、単発のデータセットがあり、AF フィルタリングが不要な場合です。
正規化された VCF/PGEN から genoray で SVAR を作成します:
from genoray import VCF, SparseVar
SparseVar.from_vcf("normed.svar", VCF("normed.bcf"), max_mem="4g") # writes a .svar/ directory
SVAR は Dataset.open 時に、metadata.json → 呼び出し側の svar= 引数 → 記録された相対パス → 記録された絶対パス → 兄弟の *.svar の順で解決されます。docs/source/format.md(「open 時の SVAR 解決」)と _dataset/_svar_link.py を参照してください。レガシーなシンボリックリンクベースの SVAR レイアウト: gvl.migrate_svar_link(path) を一度実行してアップグレードしてください。
.svar2 — 読み取りバウンドのスパースバリアント形式
.svar2 は genoray のより新しいスパースな列指向のバリアントストアです。.svar、BCF、PGEN とまったく同じように gvl.write に渡してください — gvl.write(path, bed, variants="cohort.svar2") または variants=SparseVar2("cohort.svar2") のように。.svar と同様、データセットはバリアントごとの配列を重複させる代わりにバックリファレンス(metadata.json → svar2_link)を保存するため、.svar2 ストアは読み取り時にアクセス可能なままでなければなりません。
.svar(その読み取りパスは区間探索木 + クエリ対象ウィンドウに対する読み取りごとの密な union を構築します)とは異なり、.svar2 をバックエンドとするデータセットは読み取りバウンドのパスで再構築します: gvl.write は、バリアントを保持する各 (region, sample, ploid) の var-key ウィンドウを <dataset>/genotypes/svar2_ranges/ の下にキャッシュし(データセットの選択されたサンプルに合わせてサイズ設定され、.svar2 コホート全体ではありません)— スパースな region-CSR テーブルとして、空でないウィンドウあたり 28 バイト、コホート規模では小さなもの(All of Us chr22 グリッドで約 504 MB。下記の「よくある落とし穴」の箇条書きを参照)— そして読み取り時に gvl はそのキャッシュから直接ギャザーし、オール Rust のカーネルを呼び出します — 区間探索木の構築も、読み取りごとの密な union の再構築もありません。.svar2 ストアは通常、特に大規模コホートでは、.svar よりもディスク上で小さくなります。docs/source/faq.md を参照してください。
.svar2 は Dataset.open 時に .svar と同じ順序で解決されます: 呼び出し側の svar2= 引数 → 記録された相対パス → 記録された絶対パス → 兄弟の *.svar2。Dataset.open(path, svar2=<override>) は svar= を反映します。docs/source/format.md(「open 時の .svar2 解決」)を参照してください。
フェーズ 1 のスコープ — サポートされない組み合わせは NotImplementedError を発生させます。 .svar2 をバックエンドとするデータセットは、4 つの出力モードすべて(haplotypes、variants、variant-windows、ハプロタイプ再整合された tracks)を .svar/union-oracle バックエンドとバイト単位で同一にサポートし(純粋な欠失の ALT バイトを除く — 以下を参照)、with_seqs("variant-windows")(ref="window"、alt ∈ {"window", "allele"})、unphased_union("variants" と "variant-windows" の両方の出力に対して)、および var_fields で選択された store INFO/FORMAT フィールド(同じく "variants" と "variant-windows" の両方に対して。以下の Dataset.open の var_fields を参照)はすべて .svar2 用に完全に配線されています。プレーンなハプロタイプ出力は、スプライシング、var_filter="exonic"、および負鎖領域の自動逆相補化もサポートします。以下はまだ配線されておらず、黙って誤計算する代わりに明確なエラーを発生させます:
variants、variant-windows、またはハプロタイプ再整合されたトラックを用いたスプライシング。- 非ハプロタイプ出力またはハプロタイプ再整合されたトラックを用いた
var_filter="exonic"。 min_af/max_afフィルタリング。annotatedハプロタイプ(with_seqs("annotated"))。VarWindowOpt(ref="allele")(ベアアレル REF モード。.svar2の上流でもブロックされます — REF アレルは保存されません)。- ハプロタイプ再整合されたトラックを用いた逆相補化。
- 固定長(整数の
output_length)のハプロタイプ再整合 トラック出力(固定長でのプレーンなハプロタイプ出力は問題ありません — ガードされているのはトラックカーネルのみです)。 max_jitter>0で書き込まれた、またはjitter>0で読み込まれたデータセットに対するvariants/variant-windows出力(読み込み境界のデコードはジッター後のウィンドウに右クリップしません。ハプロタイプとトラックは影響を受けず、ジッターを完全にサポートします)。.svar2バリアントソースに対するgvl.write(..., extend_to_length=False)(書き込み時。NotImplementedErrorを発生させます —.svar2ソースはデフォルトのextend_to_length=Trueを使用する必要があります)。
(1 回のクエリで複数のコンティグにまたがるトラックに対する FlankSample の挿入フィルは、現在サポートされており、.svar バックエンドとバイト単位で同一です — issue #267。)
variants/variant-windows の ALT バイトは純粋な欠失において .svar と異なります(バグではなくフォーマットの慣習)。 純粋な欠失(例: VCF GTA>G)の場合、.svar データセットに対する with_seqs("variants") は VCF アンカーベースを ALT(b"G")として返しますが、.svar2 データセットはアトマイズされた空の ALT(b"")を返します — これが genoray の .svar2 フォーマットが純粋な欠失を表現する方法です。同じ慣習は with_seqs("variant-windows") にも引き継がれます: ref_window は .svar/.svar2 間でバイト単位で同一ですが、alt/alt_window は同じ理由で純粋な欠失レコードにおいて異なります。再構築されたハプロタイプは両バックエンド間でバイト単位で同一です(どちらもシーケンスを構築する際に ALT を同一に消費します)。生のアレル/ウィンドウのバイトのみが純粋な欠失レコードにおいて異なります。docs/source/faq.md を参照してください。
シンボリック/ブレークエンドバリアントは .svar と同様に拒否されますが、.svar2 では拒否が上流、つまり .svar2 変換時に発生します(store フォーマットがそれらを表現できないため) — .svar2 はすでにフィルタリングされたソースから構築する必要があります。gvl は、マテリアライズされた .svar に対して再フィルタリングできないのと同様に、マテリアライズされた .svar2 に対しても再フィルタリングできません。
gvl.write — 主な引数
gvl.write(
path,
bed,
variants=None,
tracks=None,
annot_tracks=None,
samples=None,
max_jitter=None,
overwrite=False,
max_mem="4g",
extend_to_length=True,
)
注目すべき点:
bed:chrom, chromStart, chromEnd(0 始まり)を持つパスまたは polars DataFrame。オプションのstrand(+/-/.)は読み取り時の逆相補鎖変換を制御します。追加の列はDataset.regions上で保持されます。tracks:gvl.BigWigs(またはそのリスト)、あるいはgvl.Table。それぞれが一意の.nameを持つ必要があります。BigWigs にはサンプル→パスのマッピングが必要です(dict、またはsample、path列を持つテーブル。BigWigs.from_tableを参照)。gvl.Tableは Rust の COITrees オーバーラップエンジンに支えられた中核的なインターバルトラックソースです(0 始まりの半開区間座標)。gvl.writeのtracks=またはannot_tracks=ソースとして直接渡せます。annot_tracks:dict[str, str | Path | pl.DataFrame | pl.LazyFrame] | None— サンプルに依存しないアノテーショントラックで、<path>/annot_intervals/<name>/に書き込まれます。各値はインターバルテーブルまたは bigWig ファイルへのパス、あるいは BED 風の列(chrom、chromStart、chromEnd、score)を持つ polars DataFrame/LazyFrame のいずれかです。アノテーショントラックはサンプルに依存しないため、サンプルごとのバリアントソースなしで読み取れます。max_jitter: 読み取り時の最大ジッター。各リージョンの両側で保存データをこの塩基数分だけパディングするため、任意のj <= max_jitterに対してDataset.with_settings(jitter=j)が機能します。extend_to_length=Trueは、すべてのハプロタイプがリージョン長以上になるまで BED の終端を越えて読み取り続けます(欠失によって出力が短くなる場合に重要)。短いハプロタイプで許容できるなら、より高速な書き込みのためにFalseに設定します。.svar2バリアントソースではサポートされていません — そこではextend_to_length=FalseはNotImplementedErrorを発生させます。無効化できるのは BCF/PGEN/.svarソースのみです。samples: 含めるサンプル。None(デフォルト)はvariantsとすべてのtracksを通じて利用可能なすべてのサンプルを取得します。いずれの場合もデータセットのサンプル順序はその選択の辞書順ソートであり、表現型テーブルが通常持つ数値順ではありません("1000"は"999"より前にソートされます)。外部テーブルは位置ではなく名前でDataset.samplesに合わせてください。variantsとすべてのtracksを通じてサンプルを内部結合します。
並列処理: gvl.write は書き込みカテゴリごとに並列化されるようになりました。バリアントが最初に(逐次的に)処理されます。次に、サンプルごとの tracks と annot_tracks が並行して実行されます(joblib loky バックエンド)。max_mem の予算は、並行して実行されるカテゴリ間で分割されます。
max_mem と .svar2: .svar2 バリアントソースの場合、max_mem は、遺伝子型範囲キャッシュを生成する際に gvl.write が読み取る genoray チャンクストリームを制限します — 範囲はコンティグ全体を一度にではなく、予算に収まるサイズのサンプルごとのチャンクで生成されます。これは、コンティグごとのエントリアキュムレータ(最大のコンティグでエントリあたり約 60 バイトがピークになります。以下の「よくある落とし穴」を参照)も、永続的な genotypes/svar2_ranges/ キャッシュのディスク上のサイズ(リージョン内で観測されたバリアント数に比例し、regions x samples x ploidy ではありません)も制限しません。これらはディスク容量によって左右されます(format.md を参照)。
ソース: python/genvarloader/_dataset/_write.py。
アトミックな作成: gvl.write はプライベートな兄弟一時ディレクトリにビルドし、アトミックな os.replace で公開します。ベストエフォートの filelock は、並列ジョブが同じ宛先を共有する場合の冗長な再ビルドを回避しますが、正確性はリネームに依存します — ロックは勧告的なものにすぎません。データセットは自動再ビルドされません。ディスク上の成果物が欠落しているか破損している場合は、gvl.write を再実行してください。
対象外: genoray の .gvi インデックスファイルと pysam の .fai/.gzi インデックスファイルはこれらのライブラリによって作成され、gvl のアトミック/ロック付き作成ではカバーされません。これらのファイルのインデックス作成をトリガーする並行ジョブは、上流ライブラリの動作に依存します。
gvl.update — 既存のデータセットにトラックを追加する
gvl.update(
dataset, # str | Path | Dataset
tracks=None, # BigWigs | Table | Sequence[BigWigs | Table] | None
annot_tracks=None, # dict[str, str | Path | pl.DataFrame | pl.LazyFrame] | None
*,
overwrite=False,
max_mem="4g",
) -> None
既存のオンディスク GVL データセットに、最初から書き直すことなくトラックを追加します。
dataset: データセットディレクトリへのパス、または開かれたDataset(その.pathが使用されます)。開いているデータセットはupdate中に読み取ることができますが、再度開くまで新しいトラックは反映されません。tracks: サンプルごとのBigWigsまたはTableソース。トラックのサンプル集合はデータセットのサンプル集合と完全に一致している必要があります(不足も余分も不可)。サンプルは自動的にデータセットの順序に並べ替えられます。<path>/intervals/<track>/に書き込まれます。annot_tracks: サンプルに依存しないソースで、gvl.writeのannot_tracksと同一です(インターバルテーブルへのパス、bigWig へのパス、または BED ライクなカラムを持つ polars DataFrame/LazyFrame)。<path>/annot_intervals/<name>/に書き込まれます。overwrite=True: 同名の既存トラックを置き換えます。False(デフォルト)の場合、名前がすでに存在するとFileExistsErrorを発生させます。max_mem: おおよそのメモリ予算で、同時に実行されるカテゴリ間で分割されます。
各トラックのサブディレクトリはアトミックに公開されます(一時的な兄弟ディレクトリに構築され、その後 os.replace で所定の位置に移動されます)ので、読み取り側が書きかけのトラックを目にすることはありません。
ソース: python/genvarloader/_dataset/_write.py。
gvl.concat — オンディスクデータセットをマージする
gvl.concat(
path, # str | Path — destination directory
datasets, # Sequence[str | Path | Dataset] — 2+ inputs
axis, # "regions" | "samples"
*,
overwrite=False,
max_mem="4g", # advisory; accepted for symmetry with gvl.write
) -> None
すべてが単一のバリアントソースを共有するデータセットをマージします — 同じ PGEN/VCF バリアントテーブル(バックエンドの種類だけでなく、コンテンツフィンガープリントによってチェックされます)、または同じ .svar/.svar2 ストアです。異なるバリアントソースから構築されたデータセットをマージすると ValueError を発生させます。少なくとも 2 つの入力を必要とします。
axis="regions": 入力は同一のサンプルを同一の順序で持つ必要があります。それらのリージョンは連結されます(コンティグ/位置でソートされます)。axis="samples": 入力は同一のリージョンと互いに素なサンプル集合を持つ必要があります。それらのサンプルはソートされた順序にマージされます。
どちらの軸も、ジェノタイプとともにサンプルごとのトラックとアノテーショントラックをマージします。対応バックエンド: PGEN/VCF、.svar、.svar2。PGEN/VCF ソースの場合、variants.arrow は最初の入力からハードリンクされ、フィンガープリントがマージ後の metadata.json に記録されます。Dataset.open はそれを再検証するため、バリアントインデックスの帯域外での書き換えは、黙って誤解決される代わりにエラーを発生させます。
コスト: gvl.concat は何も再導出せずにバイトをストリームするため、そのコストは計算ではなく I/O に比例します — マージ後のデータセットのほぼ全体のサイズを移動します。計画はストリーミングで行われ、メモリはリージョン数とサンプル数の積ではなく和に比例してスケールするため、常駐コストはマージ後のオフセット配列(マージ後の (region, sample[, ploid]) スロットごとに 1 つの int64)に入力自身のオフセット配列(入力がマージ後のグリッドを分割するため、合わせておおよそその 2 倍)を加えたものであり、マージ計画ではありません。ルーチンのステップとしてではなく、ジェノタイプを最初から再抽出するという代替手段に対する場合にのみ価値があります。完全なコストの議論と、コンティグシャードされた .svar2 ワークフロー向けのストアレベルの代替手段である genoray.SparseVar2.concat については、docs/source/write.md の「Merging datasets」を参照してください。
ソース: python/genvarloader/_dataset/_concat.py、_concat_validate.py。
Dataset.open — 主要な引数
gvl.Dataset.open(
path, reference=None, jitter=0, rng=None,
deterministic=True, rc_neg=True,
min_af=None, max_af=None, # .svar only — raises NotImplementedError on .svar2
region_names=None,
splice_info=None, # see "Spliced haplotypes"
var_filter=None, # None | "exonic"
var_fields=None, # list[str] | None — see below
*, svar=None, svar2=None,
)
reference= を指定しない場合、ジェノタイプのみのデータセットはデフォルトで "variants" ビューで開きます(RaggedVariants を生成します) — Dataset.open(path) はそのまま動作し、with_seqs は不要です。"haplotypes"、"annotated"、"reference" の各ビューはすべて reference を必要とします。reference のないデータセットで with_seqs を介してそれらを要求すると、明確な ValueError を発生させます。svar= は記録された SVAR の場所を上書きします。svar2= は .svar2 ベースのデータセットに対して同様の役割を果たします。
with_settings(dummy_variant=...) — すべての空の (region, sample, ploid) バリアントグループに gvl.DummyVariant を挿入し、すべてのグループが少なくとも 1 つのバリアントを持つようにします。空のグループのみを埋め、空でないグループは変更されません。"variants" と "variant-windows" の両方の出力種別で有効です。dummy_variant が設定されていて出力種別がそれ以外("haplotypes"、"annotated"、"reference"、または seqs なし)の場合、インデックス作成時に ValueError が発生します — このチェックは with_seqs との順序に依存しません。False はダミーパディングを無効にし、None(デフォルト)は現在の設定を変更しません。出力がサポートされていない種別のときに dummy_variant=False を設定しても、無害なノーオペレーションです。
トークン出力(付随する FlatVariants.flank_tokens と "variant-windows" のフィールド ref_window/alt_window/ベア ref/alt)では、各空グループのダミーエントリは、設定された unknown_token(アルファベット外のバイトがマップされるユーザー指定の整数 — アルファベット非依存なので、DNA/RNA では N、アミノ酸では X がこれにトークン化されます)で完全に埋められます。DummyVariant.ref/.alt バイトはダミーアレルのバイト長のみを決定し、トークン値は決定しません。空の (region, sample, ploid) グループごとの充填長: 付随する flank_tokens → 2·flank_length 個の unknown トークン、ref_window/alt_window → 2·flank_length + len(dummy allele) 個の unknown トークン、ベア ref/alt → len(dummy allele) 個の unknown トークン。(デフォルトの b"N" アレル → 長さ 1。)
スカラーフィールド(start/ilen/dosage/info[...])は従来どおり DummyVariant の値から埋められます。ダミーの充填は "variants" 出力アレルの逆相補化の前にのみ適用されるため、b"N" 以外のダミーアレルは実際のアレルと同様に負鎖領域で逆相補化されます — デフォルトの b"N" は逆相補不変です。フランクトークンとバリアントウィンドウのトークンバッファは参照向きであり、逆相補化はされません。
with_settings(unphased_union=...) — 保存された二倍体ハプロタイプを単一の一倍体配列に折り畳みます: (region, sample) ごとのコールされた ALT の和集合です。True の場合、ds.ploidy は 1 を報告し(保存された 2 の代わり)、n_variants(...) は単一の倍数性スロット(形状 (..., 1))を報告し、カウントはハプロタイプごとの単純な合計に等しくなります(ホムコールはハプロタイプごとに 1 回ずつ、計 2 回現れ、重複排除はありません)。"variants" と "variant-windows" の出力は倍数性 1 でデコードされます。ALT の出現はハプロタイプ間で連結され、ソートも重複排除も行われません。フェーズは破棄されます — 非フェーズの体細胞コールの一倍体体細胞モデリングを目的としています。ジェノタイプを持つデータセットが必要です(参照のみのデータセットでは ValueError が発生します)。"haplotypes" / "annotated" 出力とは互換性がありません — with_seqs("haplotypes") または with_seqs("annotated")(あるいはこれらのいずれかがアクティブな出力種別のときにこのフラグを設定すること)は ValueError を発生させます。issue #222 を参照してください。
フォーマット検証: Dataset.open はデータセットの format_version と構造的整合性(ファイルの存在 + サイズ)を検証します。破損したデータセットは ValueError を発生させ、gvl.write での再生成を促します。データセットは自動再構築されません。
フォーマットバージョンゲート (2.0): 現在のオンディスクフォーマットは 2.0.0 です。genvarloader < 2.0 で書き込まれたデータセット(またはバージョンなしのデータセット)を開くと、gvl.migrate(path) を指すメッセージの ValueError が発生します。より新しいメジャーで書き込まれたデータセットは、genvarloader のアップグレードを促す ValueError を発生させます。gvl.migrate(path) を一度実行すると、2.0 以前のデータセットをその場でアップグレードします — ストリーミング方式で(ピーク時の追加ディスクは 1 トラック分のインターバルストア)、冪等で、クラッシュセーフです(すべてのトラックの struct-of-arrays ファイルが永続化された後にのみメタデータが更新され、その後古い array-of-structs ファイルが削除されます)。変換するのはトラックインターバルのストレージのみで、ジェノタイプ、リージョン、参照は変更されません。
-
var_fields: list[str] | None—RaggedVariants出力に含めるバリアントフィールド。デフォルトは最小限の有用なセット["alt", "ilen", "start"]です。追加の名前(例:"ref"、"dosage"、またはソースバリアントテーブル内の任意の数値情報カラム)を渡すと、オープン時にそれらを先行して読み込みます。Dataset.available_var_fieldsのサブセットである必要があります。後からDataset.with_settings(var_fields=...)で再設定でき、新たに要求されたカラムは遅延読み込みされます。"dosage"は明示的に要求する必要があります — ディスク上にdosages.npyが存在する場合でも、自動的に追加されることはありません。組み込みフィールド(alt、start、ref、ilen、dosage)およびバリアントごとの INFO カラムに加えて、genoray の.svarは任意の per-call(Number=G)FORMAT フィールドを<svar>/metadata.json["fields"]に登録できます。これらはDataset.available_var_fieldsに現れ、Dataset.open(..., var_fields=[...])またはwith_settings(var_fields=[...])で要求できます。それぞれがvariants、variant-windows、flat出力において、ジェノタイプに対応する per-call のラグドフィールドとして現れます。FORMAT フィールドは同名の INFO カラムをシャドウします。.svar2では、available_var_fieldsは["alt", "ilen", "start"]に、その.svar2が書き込まれた際のストアフィールドを加えたものです —"ref"と"dosage"は.svar2ソースで利用可能なフィールドではなく、いずれかを要求するとエラーになります(これらは BCF/PGEN/.svarでのみ有効です)。それ以外に、var_fieldsはストア自体のスカラー数値 INFO/FORMAT フィールドも公開します — それらは.svar2がgenoray.SparseVar2.from_vcf(info_fields=[...], format_fields=[...])を介して書き込まれた際のものです(そこでは裸のstr名も機能します)。そもそも.svar2ストアに存在できるのはスカラー数値フィールドのみです —Number=1またはNumber=Aの INFO/FORMATType=Integer/Float、および INFOType=Flag(bool として保存)で、それ以外は書き込み時に genoray によって拒否され、gvl には到達しません。gvlはストアが既に保持しているものを読み取るだけです — フィールドを追加することはできず、ストアが持っていないフィールドを再要求するとエラーになります(available_var_fieldsに存在しないため)。Dataset.available_var_fieldsは各ストアフィールドのキーを公開し、それはgenoray.SparseVar2.available_fieldsを情報源とします。ストアの INFO/FORMAT 名前空間で一意であれば裸のフィールド名、そうでなければ"INFO/<name>"/"FORMAT/<name>"となります。組み込み名(alt/start/ref/ilen/dosage)が常に優先されます — たとえばaltという名前のストアフィールドは決して公開されず、組み込みをシャドウすることはできません。値はストアの dtype を正確に保ち、拡張は行いません(i32フィールドはint32に、f32フィールドはfloat32にデコードされます)。また VCF に存在しないエントリは、ストアに保存されたデフォルトをそのまま保持します(デフォルトを宣言せずに定義された float フィールドではNaN)。両方のエントリポイントは同じ svar2 再構築器にルーティングされます:gvl.Dataset.open(path, reference=..., var_fields=[...])およびds.with_seqs("variants")/.with_settings(var_fields=[...])。両方の出力モードでサポートされています:"variants"(フィールドは返されたRaggedVariantsに現れ、たとえばrv["AF"]、alt/start/ilenのバリアントオフセットを共有します)および"variant-windows"(フィールドはwin.fields["AF"]にstart/ilenと並んで現れます)。FORMAT フィールドの値は、その行が属するサンプルの値です(サンプル 0 ではありません)。空の(region, sample, ploid)グループは、他のスカラーフィールドと同じDummyVariant.info[<key>]メカニズム(上記のwith_settings(dummy_variant=...)を参照)を介して各ストアフィールドを埋めます。ユーザー指定の値があればそれを使用し、そうでなければ float カラムにはNaN、整数カラムには0を使用します。
出力モード — with_seqs × with_tracks
with_seqs(kind) はシーケンス出力チャネルを選択します:
kind | 返すもの | 使用する場面 |
|---|---|---|
"reference" | 参照配列 (S1) | ベースライン / パーソナライズなし |
"haplotypes" | インデルを含むパーソナライズされたハプロタイプ (S1) | 標準的なバリアントを考慮したモデリング |
"annotated" | AnnotatedHaps (haps + var_idxs + ref_coords) | バリアント/参照座標にマッピングし直す必要がある場合 |
"variants" | RaggedVariants (バリアントのみ、配列なし) | バリアント中心のタスク |
"variant-windows" | FlatVariantWindows (アレルごとのウィンドウ/アレルトークンバッファ。フラットモードのみ) | 各バリアント周辺のトークン化されたモデル入力 |
None | 配列なし | トラックのみのデータセット |
"variant-windows" には VarWindowOpt の第2引数 (with_seqs("variant-windows", gvl.VarWindowOpt(...)))、with_output_format("flat")、および参照ゲノムが必要です。with_settings からフランク設定を継承しません。
variant-windows は with_settings(realign_tracks=False) が設定されている場合、トラックと組み合わせることができます。返されるトラック/インターバルは参照座標 (そのまま) です。Float トラックは FlatRagged として、インターバルトラックは FlatIntervals として返されます。
with_tracks(tracks=..., kind=...) はトラックを選択します:
tracks:None(デフォルト)、False(無効化)、単一の名前、または名前のリスト。kind:"tracks"(再アラインメントされた数値) または"intervals"(生のインターバル表現)。
トラックのハプロタイプ座標への再アラインメントは with_settings(realign_tracks=True) (デフォルト) で制御されます。参照座標 (「そのまま」) のトラックには realign_tracks=False を設定します。realign_tracks=False は、バリアントを考慮した任意の seq モードでの kind="intervals"、および variant-windows + トラックの場合に必須です。with_insertion_fill には realign_tracks=True が必要です。
with_settings(parallel=...) — このデータセットの読み取りの並列化ポリシーです。True は Rust カーネルを強制的にマルチスレッド化し、False は強制的に直列化し、"auto" (デフォルト) は出力サイズに基づいてバッチごとに決定します。明示的な True/False は GVL_FORCE_PARALLEL 環境変数を上書きします — 優先順位は 明示的な設定 > 環境変数 > サイズゲート — そのため、スクリプトの並列化は周囲の状態に依存せず、スクリプトから読み取ることができます。"auto" は環境変数に委ねるため、これを設定しないデータセットはこれまでと同じように動作します。この設定はデータセットごとであり、データローダーのワーカープロセスにも引き継がれます。これは並列化を行うかどうかを制御するもので、スレッド数ではありません。ワーカー数は rayon がグローバルプールの初期化時に GVL_NUM_THREADS を読み取るためインポート時に固定され、データセットごとに変えることはできません。issue #352 を参照してください。
with_len(L) は出力形状を制御します:
"ragged"(デフォルト):gvl.Raggedを返します (アイテムごとに可変長)。"variable": バッチ内の最長アイテムに右パディングされた NumPy 配列 (seqs ではN、トラックでは0)。- 整数
L: 固定長。ジッター/ランダムシフト/切り詰め/よりパーソナライズされたデータでのパディングを組み合わせてLを満たします。L + 2·jitter ≤ min(region_length) + 2·max_jitterを満たす必要があります。
with_len に基づいて RaggedDataset または ArrayDataset (凍結されたデータクラスビュー) のいずれかを返します。図については docs/source/dataset.md を参照してください。
with_output_format(fmt) は eager インデックスによって返されるコンテナ型を選択します:
fmt | 返されるコンテナ型 | デフォルト? |
|---|---|---|
"ragged" | Ragged / RaggedVariants / RaggedAnnotatedHaps (すべて seqpro._core.Ragged ベース) | はい |
"flat" | 純粋な numpy の FlatRagged / FlatVariants / FlatAnnotatedHaps / FlatIntervals | いいえ |
"flat" モードではホットパスに無駄がなく、返されるコンテナは .data(フラットな numpy 配列)と .offsets(int64)を保持します。すべてのフラット型には、_core.Ragged ベースの形式に戻す .to_ragged() があります。密化へのエスケープハッチは型ごとに異なります。FlatRagged には .to_fixed(length) と .to_padded(pad_value) があり、FlatAnnotatedHaps には .to_fixed(length) と .to_padded()(引数なし — フィールドごとの pad デフォルトを使用)があります。FlatVariants/FlatAlleles は .to_ragged() のみを公開します(加えて .reshape/.squeeze)。 |
ds_flat = ds.with_output_format("flat")
result = ds_flat[0:8, :] # FlatRagged or FlatAnnotatedHaps or FlatVariants
# direct tensorization — no awkward round-trip
import torch
t = torch.from_numpy(result.data)
# or convert back
ragged = result.to_ragged()
with_output_format は with_len および subset_to と直交し、これらと組み合わせて使用できます。
スコープに関する注意: "flat" モードでは、kind="intervals" のトラックは FlatIntervals を返します(.to_ragged() → RaggedIntervals、フィールド .starts/.ends/.values はそれぞれ FlatRagged)。Float(数値)トラックはフラットモードで FlatRagged を返します。seqs/haplotypes/annotated-haps/reference および variants の出力もこれまでどおりフラット化されます。
Flat variants の追加機能 — 同乗するフランクトークンとバリアントウィンドウ:
import seqpro as sp
import genvarloader as gvl
# Both paths need tracks disabled — the flat variants/windows channel is not
# produced when tracks are active (see gotchas).
# (a) ride-along flank tokens on the "variants" output
fv = (ds.with_tracks(False).with_seqs("variants").with_output_format("flat")
.with_settings(flank_length=128, token_alphabet=sp.DNA.alphabet,
unknown_token=len(sp.DNA)))[0:8]
fv.flank_tokens # FlatRagged, shape (b, p, ~v, 2*128), or None if not configured
# (b) per-allele windows: ref as a flanked window, alt as a bare tokenized allele
fw = (ds.with_tracks(False).with_output_format("flat")
.with_seqs("variant-windows",
gvl.VarWindowOpt(flank_length=128, token_alphabet=sp.DNA.alphabet,
unknown_token=len(sp.DNA), ref="window", alt="allele")))[0:8]
fw.ref_window # flanked ref window tokens (two-level token buffer)
fw.alt # bare alt allele tokens (no flanks); fw.alt_window is None
fw.ref_window.shape # the window buffer's own shape: (b, p, ~v, ~len)
同乗する FlatVariants.flank_tokens(with_seqs("variants") + with_settings(flank_length=L, token_alphabet=..., unknown_token=...)): 返される FlatVariants に形状 (b, p, ~v, 2L) の FlatRagged を追加します。バリアントごとに、バッファは [flank5 | flank3] の参照コンテキストトークン(それぞれ長さ L)を保持します。座標規則: flank5 = [start-L, start)、flank3 = [end, end+L)(ここで end = start - min(ilen, 0) + 1)。token_alphabet(str、bytes、または seqpro.NucleotideAlphabet — 例: sp.alphabets.DNA / sp.DNA.alphabet。with_settings/build_token_lut の境界で bytes に正規化されます)と unknown_token(int)が一緒になって 256 エントリの byte→token LUT を構築します(seqpro 形式): 各アルファベットバイト → その 0 ベースのインデックス。その他のすべてのバイト(N や範囲外のパディングを含む)→ unknown_token。flank_length=0/None で無効化されます。token_alphabet と unknown_token は両方同時に設定する必要があります。トークンの dtype は、最大トークン ID ≤ 255 の場合は uint8、それ以外は int32 です。オフセットは int64 です。with_settings(dummy_variant=...) が設定されている場合、各空の (region, sample, ploid) グループの flank_tokens 行は、unknown_token が 2L 個連続したものになります。
VarWindowOpt / FlatVariantWindows(with_seqs("variant-windows", opt)): 各バリアントは、VarWindowOpt.ref / VarWindowOpt.alt ∈ {"window", "allele"} を介して ref と alt に対して独立に選択される 2 つのモードのいずれかで、固定長のトークンバッファを取得します:
"window": フランク付き + トークン化 — ref-window = トークン化された[start-L, end+L)の参照リード。alt-window = トークン化されたflank5 · alt-allele · flank3のアセンブリ。"allele": フランクなしの、トークン化された裸のアレル(ref または alt の塩基)。
FlatVariantWindows は .ref_window / .ref のちょうど一方(他方は None)と、.alt_window / .alt のちょうど一方(他方は None)を設定します。.fields はスカラーの FlatRagged の dict です(start/ilen/dosage/info。生のバイトアレルは除外されます)。フランクとウィンドウは参照指向です — rc_neg=True であっても逆相補化されません。"variant-windows" ではスプライシングはサポートされません。with_settings(dummy_variant=...) が設定されている場合、各空の (region, sample, ploid) グループは、すべて unknown_token のエントリ 1 つでパディングされます: ref_window/alt_window("window" モード)では長さ 2·flank_length + len(dummy allele) トークン、裸の ref/alt("allele" モード)では len(dummy allele) トークンです。
トラック挿入フィル(haps と tracks が同時に存在する場合のみ)
インデルにより、トラック長が参照長と異なる場合があります。Dataset.with_insertion_fill(fill) は、挿入された位置に何を書き込むかを制御します。これは、データセットがハプロタイプとトラックの両方を返す場合にのみ有効です。純粋な参照(pure-ref)および純粋なハプロタイプ(pure-hap)のデータセットでは無視されます(適用しようとするとエラーが発生します)。
| ストラテジー | 動作 |
|---|---|
gvl.Repeat5p() (デフォルト) | バリアント POS の値を挿入領域全体に繰り返します。 |
gvl.Repeat5pNormalized() | track[POS] / (insertion_len + 1) を繰り返します。合計を保持します。 |
gvl.Constant(value=nan) | 挿入領域全体で定数値(デフォルトは NaN)を使用します。 |
gvl.FlankSample(flank_width=5) | POS 周辺の 2·flank_width+1 のウィンドウから、復元抽出でリサンプリングします。 |
gvl.Interpolate(order=1) | 両側の参照値の間で多項式補間(次数 1/2/3)を行います。 |
単一のストラテジーを渡す(すべてのトラックに適用)か、dict[track_name, strategy] を渡します(欠落しているトラックは Repeat5p にフォールバックします)。ソース: python/genvarloader/_dataset/_insertion_fill.py。
スプライスされたハプロタイプ
スプライシングは Dataset.open でオプトインします(または with_settings 経由)。これは 1 つのトランスクリプトの BED 行をグループ化し、サンプルごとにエクソンレベルの配列/トラックを連結します。
splice_bed = gvl.get_splice_bed("annotation.gtf", transcript_support_level="1")
gvl.write(path="splice.gvl", bed=splice_bed, variants="normed.svar")
sds = gvl.Dataset.open(
"splice.gvl",
reference="ref.fa",
splice_info=("transcript_id", "exon_number"), # tuple = (group_col, order_col)
var_filter="exonic", # optional: drop intronic variants
)
splice_info は以下を受け付けます:
- カラム名の文字列(単一のグループ化カラム、順序は BED 行の順序から推測されます)、または
(group_col, order_col)タプル(明示的な順序付け、例えばエクソン番号)。
get_splice_bed は TSL フィルタリングとオプションの「CDS 長が 3 の倍数」フィルタを用いて GTF→BED を実行します。独自のスプライス BED を作成するには、BED に transcript_id(または任意のグループ化カラム)と exon_number カラムを含めるだけです。docs/source/splicing.ipynb を参照してください。
RefDataset のスプライシング
gvl.RefDataset は Dataset.open と同じ splice_info 引数を受け付けます。トランスクリプト ID のカラム名(行がすでにスプライス順になっている場合)か、エクソンを並べ替えるための (group_col, sort_col) タプルを渡します。with_settings(splice_info=False) は既存の RefDataset でスプライシングを無効化します。再度有効化するには新しい値を渡してください。スプライシングには output_length が {"ragged", "variable"} であること、jitter=0、deterministic=True が必要です。subset_to(transcript_ids) は Dataset と同様に動作します。
ref = gvl.Reference.from_path("hg38.fa.bgz")
bed = gvl.get_splice_bed("annotations.gtf")
ref_ds = gvl.RefDataset(ref, bed, splice_info="transcript_id")
seqs = ref_ds[:] # Ragged[S1], one row per transcript
サイトのみのバリアント(例: ClinVar)
gvl.sites_vcf_to_table(vcf) → pl.DataFrame(二対立 SNP のみ)を使用し、ArrayDataset[AnnotatedHaps, ...] を gvl.DatasetWithSites(ds, sites, max_variants_per_region=1) でラップします。(wt_haps, mut_haps, flags[, tracks]) を返します。flags は適用済み / 重複により削除 / 既存をエンコードします。_variants/_sitesonly.py を参照してください。
データローダーのプリフェッチ (to_dataloader の mode=...)
Dataset.to_dataloader() は、フェッチを粗くするためのオプションの mode を受け付けます。gvl のスループットはフェッチサイズに応じてスケールするため(内部のマルチスレッド化がオーバーヘッドを償却します)、1 回の大きな dataset[r_idx, s_idx] 呼び出しをミニバッチにスライスするほうが、バッチごとの多数の小さな呼び出しよりも優れた性能を発揮します。
loader = ds.to_dataloader(
batch_size=32,
mode="double_buffered", # or "buffered", or None
buffer_bytes=2 * 1024**3, # total RAM budget; split across slots in double mode
copy=True, # zero-copy opt-out (default True = safe)
heartbeat_seconds=60.0, # double_buffered: max wait per chunk before liveness check
)
モード:
None(デフォルト) — 通常のtorch.utils.data.DataLoader。既存の動作です。"buffered"— メインプロセスが呼び出しごとに 1 つのチャンクをフェッチし(buffer_bytesに合わせてサイズ設定)、ミニバッチにスライスします。再充填のレイテンシは見えますが、多数のバッチにわたって償却されます。"double_buffered"— サブプロセスのプロデューサーが一方の shm スロットを埋める間に、コンシューマーがもう一方を排出します。再充填のレイテンシが隠蔽されます。ファイルベースのDataset.open(path)が必要です。
フラット出力はバッファリングモードと組み合わせられます。 ds.with_output_format("flat").to_dataloader(mode="buffered" | "double_buffered") は、Ragged / RaggedVariants の代わりに Flat* ミニバッチ(FlatRagged / FlatVariants / FlatAnnotatedHaps / FlatVariantWindows)を生成し、トランスポート経路での不格好さはゼロです — double_buffered プロデューサーはフラットバッファを書き込み、コンシューマーは再ラップせずにそれらを読み戻します。各バッチは .to_fixed(length) / .to_padded(pad) で密化するか、batch.data / batch.offsets を torch.from_numpy でラップします(オフセットは int64 です。torch の Nested テンソルにするには int32 にキャストしてください)。.to_ragged() で _core.Ragged を基盤とする型に再ラップします(ragged モードと要素単位で同一です)。モードの前提条件は変わりません。double_buffered は依然としてファイルベースの Dataset.open(path) を必要とし、依然としてスプライスされたデータセットとデフォルト以外の insertion_fill を拒否し、ハプロタイプ/アノテーション付き出力には依然として deterministic=True が必要です。"variant-windows" 出力(with_seqs("variant-windows", VarWindowOpt(...)))および同行フランクトークンを持つフラットな "variants" 出力(with_settings(flank_length=...))は、mode="buffered" と mode="double_buffered" の両方でサポートされ、mode=None とバイト単位で同一です — dummy_variant が設定されている場合も含みます(プロデューサーサブプロセスがそれを再生し、空グループのダミー充填は double_buffered のスロットサイズ計算に含まれます)。
前提条件(いずれも構築時に ValueError を発生させます):
with_seqs in {"haplotypes", "annotated"}にはdeterministic=Trueが必要です(with_settings(deterministic=True)で設定)。referenceおよびvariantsモードには決定性の要件はありません。- スプライスされたデータセットはサポートされません。
num_workers > 0は拒否されます — 新しいローダーが並行処理戦略そのものです。- 正確なフットプリントがスロットごとの容量を超える単一のミニバッチは、問題のあるサイズと是正用のパラメータ(
batch_size↓、buffer_bytes↑)とともに発生させます。
フットプリントは Dataset._output_bytes_per_instance(...) を介して正確に計算されます(haplotype_lengths、n_variants、アレルオフセットテーブルを使用) — Zipf スタイルの最悪ケースの余裕はありません。
その他の公開サーフェス(一行説明)
gvl.Reference.from_path(fasta, contigs=None, in_memory=True)— FASTA (.fa/.fa.bgzへのパス、または.gvlfaキャッシュディレクトリ) をラップします。隣接する.gvlfaキャッシュディレクトリをビルド/再利用します (自己記述的で、フィンガープリント検証済み。レガシーな.fa.gvlキャッシュは自動移行されます)。キャッシュはベストエフォートのロックの下でアトミックに (一時ファイル +os.replace) ビルドされるため、1 つのリファレンスを共有する並行ビルダーは安全です。キャッシュは古くなった場合や存在しない場合、そのソースから自動再ビルドされます。in_memory=Falseはメモリマップからオンデマンドで読み取ります (RAM 使用量が少ない) が、FASTA のコンティグ順序を保持するため、contigsはNoneか、FASTA の完全な順序と正確に一致する必要があります —contigsの並べ替えや部分集合化にはin_memory=Trueが必要です (そうでない場合はValueErrorを送出します)。gvl.read_bedlike(path)/gvl.with_length(bed, L)— BED ヘルパー (seqproから再エクスポート)。gvl.Ragged、gvl.RaggedAnnotatedHaps、gvl.RaggedVariants、gvl.RaggedIntervals— ragged 戻り値コンテナ。すべてseqpro.rag.Ragged(_core.RaggedRust バックエンド) に支えられており、awkwardではありません。RaggedVariantsはseqpro.rag.Raggedのサブクラス (class RaggedVariants(seqpro.rag.Ragged)) であるため、isinstance(rv, Ragged) is Trueです。構造メソッド — インデックス操作、reshape、squeeze、to_packed— は基底から継承され、RaggedVariants型を保持します (位置/構造操作はRaggedVariantsを返します)。文字列キー (rv["start"]) は裸のRaggedフィールドを返し、RaggedVariantsではありません。reshapeは新しい形状を、展開した int として — 例えばrv.reshape(1, 2, None)— あるいは単一のタプルとしてrv.reshape((1, 2, None))受け取ります。基底のRaggedシグネチャは両方を受け付けます。squeeze(axis=None)は実際の軸圧縮 (基底セマンティクス) です — 任意のサイズ 1 の軸を圧縮し、固定の「軸 0 を落とす」ではありません。int インデックスは先頭軸を潰し (numpy と整合)、スライス/配列インデックスはそれを保持します。アレルフィールド (rv.alt[b][h]、rv.ref[b][h]) のインデックス操作は、そのハプロタイプのアレルをバリアントごとに返し、rv.start[b][h]/rv.ilen[b][h]と 1 対 1 で整列するため、zip(rv.start[b][h], rv.alt[b][h])は各位置をそれ自身のアレルとペアにします。これには seqpro >= 0.22 が必要です。それより古い seqpro では、同じ式がグループのすべてのアレルを連結した単一のbytesを返し、マルチバイト (indel) アレルを含むグループではスカラーフィールドとの整列が暗黙に崩れていました。名前付きプロパティ (.alt、.ref、.start、.ilen、.end) が主要なアクセスポイントです。追加フィールド (例えばAF、カスタム FORMAT フィールド) もrv["field"]またはrv.field(__getattr__経由) でアクセスできます。RaggedVariants自体は__eq__を定義していません (ラッパーレベルの==は Python のオブジェクト同一性であり、要素ごとではありません)。内容を比較するには個々のフィールドを比較してください — 例えばrv["alt"] == other_altやrv.start == other_start— これらはseqpro.rag.Raggedの ufunc ベース (要素ごと) の比較を使用します。RaggedVariantsに保持されるドメインメソッド:.rc_()、.pad()、.to_nested_tensor_batch()。派生読み取り専用プロパティ:.ilen、.end。フィールド:.alt、.ref、.start、.dosage。gvl.FlatRagged—Raggedのフラット版:.data(フラットな numpy 配列)、.offsets(int64)、.shape。メソッド:.to_ragged()、.to_fixed(length)、.to_padded(pad_value)、.reshape(shape)、.squeeze(axis)。ソース:python/genvarloader/_flat.py。gvl.FlatIntervals—with_tracks(kind="intervals")+with_output_format("flat")が返すフラットバッファのインターバルコンテナ。フィールド.starts/.ends/.valuesはFlatRagged。.to_ragged()→RaggedIntervals、.reshape(...)、.squeeze(...)、.shape。ソース:python/genvarloader/_ragged.py。gvl.FlatAnnotatedHaps—RaggedAnnotatedHapsのフラット版: フィールド.haps、.var_idxs、.ref_coords(それぞれFlatRagged)。メソッド:.to_ragged()、.to_fixed(length)、.to_padded()、.reshape(shape)、.squeeze(axis)。ソース:python/genvarloader/_flat.py。gvl.FlatVariants—RaggedVariantsのフラット版:.fieldsはフィールド名をFlatRagged(スカラーフィールド:start/ilen/dosage/info) またはFlatAlleles(alt/ref) にマッピングする dict。.shapeはfields["start"].shapeに委譲します。.flank_tokens: 形状(b, p, ~v, 2L)のオプションの同行FlatRagged(with_settings(flank_length=L, ...)が設定されている場合に設定され、それ以外はNone)。メソッド:.to_ragged()、.reshape(shape)、.squeeze(axis)。ソース:python/genvarloader/_dataset/_flat_variants.py。gvl.FlatAlleles— アレルフィールド用の 2 レベルのフラットバイト文字列:.byte_data(uint8)、.seq_offsets(バリアントごとのバイトオフセット、int64)、.var_offsets((バッチ×倍数性) 行ごとのバリアントオフセット、int64)、.shape。メソッド:.to_ragged()、.reshape(shape)、.squeeze(axis)。ソース:python/genvarloader/_dataset/_flat_variants.py。gvl.FlatVariantWindows— フラットモードでwith_seqs("variant-windows", VarWindowOpt(...))が返すもの。.fields: スカラーFlatRaggedの dict (start/ilen/dosage/info。生のバイトアレルは破棄されます)。アレルごとのトークンバッファ —.ref_window(フランク付き ref ウィンドウ、"window"モード) または.ref(裸の ref アレルトークン、"allele"モード) のいずれか 1 つだけが設定されます。.alt_window/.altも同様です。各非 None バッファは形状(b, p, ~v, ~len)の 2 レベルトークンバッファ (内部_FlatWindowであり、公開FlatRaggedではありません) で、独自の.to_ragged()を持ちます。コンテナの.shapeはfields["start"].shapeに委譲します。メソッド:.to_ragged()(ragged パーツの dict を返す)、.reshape(shape)、.squeeze(axis)。ソース:python/genvarloader/_dataset/_flat_variants.py。gvl.VarWindowOpt—with_seqs("variant-windows", ...)用のフローズン設定 dataclass。フィールド:flank_length(int)、token_alphabet(str | bytes | sp.NucleotideAlphabet、例えばsp.alphabets.DNA。構築時にbytesに正規化)、unknown_token(int)、ref∈{"window","allele"}、alt∈{"window","allele"}。refとaltは独立に選択されます。"window"= フランク付き + トークン化されたリファレンスリード (ref) または flank·alt·flank のアセンブリ (alt)、"allele"= フランクなしの裸のトークン化アレル。ソース:python/genvarloader/_dataset/_flat_variants.py。gvl.DummyVariant—with_settings(dummy_variant=...)で使用するフローズン dataclass。フィールドとデフォルト:start: int = -1、ilen: int = 0、dosage: float = 0.0、ref: bytes = b"N"、alt: bytes = b"N"、info: dict = {}。指定されていないinfoキーは、整数カラムでは0、浮動小数点カラムではNaNにデフォルト設定されます。ソース:python/genvarloader/_dataset/_flat_variants.py。gvl.migrate(path)— 2.0 より前の (struct-of-arrays の) データセットをフォーマット 2.0 (struct-of-arrays) にその場でアップグレードします。ストリーミング、冪等、クラッシュセーフ。intervals/<track>/とannot_intervals/<track>/のインターバルストレージを変換し、metadata.jsonを更新します。すでに 2.0 のデータセットでは no-op (残存する AoS のクリーンアップを伴う) です。ソース:python/genvarloader/_dataset/_migrate.py。(レガシーな SVAR シンボリックリンクレイアウトをアップグレードするgvl.migrate_svar_linkとは異なります。)gvl.to_nested_tensor(ragged)— PyTorch のネストテンソルに変換します (torchが必要)。gvl.get_dummy_dataset()— 例/テスト用の小さなインメモリデータセット。gvl.RefDataset— リファレンスのみのデータセット (ジェノタイプなし)。gvl.Table— Rust の COITrees オーバーラップエンジンに支えられたコアのインターバルトラックソース。0 始まりの半開座標。正の幅のインターバルを前提とします。gvl.writeとgvl.updateのtracks=またはannot_tracks=ソースとして直接使用できます。追加のインストールは不要です — コアパッケージの一部として同梱されています。ブルートフォースの numpy オラクル + プロパティテストによる CI カバレッジがあります。gvl.data_registry.fetch(name)— 公開テスト/デモデータセットをダウンロードします。 完全なリストはpython/genvarloader/__init__.pyの__all__にあります。
ディスク上のレイアウト(クイックリファレンス)
ds.gvl/
├── metadata.json # version, samples, contigs, ploidy, max_jitter, svar_link?
├── input_regions.arrow # BED + region index map
├── genotypes/ # variant_idxs.npy, dosages.npy, variants.arrow
│ # (absent when sourced from .svar; see svar_link)
│ # svar2_ranges/ present iff sourced from .svar2 (see svar2_link)
├── intervals/<track>/ # per-sample track data (BigWigs / Table)
└── annot_intervals/<track>/ # sample-independent annotation track data
フォーマット 2.0 では、各 intervals/<track>/(および annot_intervals/<track>/)ディレクトリは、その間隔を struct-of-arrays として保存します — 3 つの連続ファイル starts.npy(int32)、ends.npy(int32)、values.npy(float32)が 1 つの offsets.npy(int64)を共有し、フォーマット 1.x の単一の intervals.npy レコード配列を置き換えます。これにより、連続した memmap が Python→Rust の境界をゼロコピーで越えられます。1.x データセットは gvl.migrate(path) でアップグレードしてください(上記のフォーマットバージョンゲートを参照)。
完全なスキーマ、バージョニング、SVAR リンクの詳細については docs/source/format.md を参照してください。
次に参照すべき場所
| 目的… | 参照先… |
|---|---|
| エンドツーエンドの RNA-seq の例 | docs/source/geuvadis.ipynb |
| スプライシングのチュートリアル | docs/source/splicing.ipynb |
| ディープラーニング評価パイプライン | docs/source/basenji2_eval.ipynb |
| BED / BigWig / bcftools のレシピ | docs/source/write.md |
Dataset の形状、ragged/var/fixed | docs/source/dataset.md |
| ディスク上のフォーマット + SVAR 解決 | docs/source/format.md |
FAQ(with_* の設計、型付け) | docs/source/faq.md |
| 自動生成リファレンス | docs/source/api.md → https://genvarloader.readthedocs.io |
gvl.write / gvl.update の内部 | python/genvarloader/_dataset/_write.py |
gvl.concat の内部 + 前提条件 | python/genvarloader/_dataset/_concat.py、_concat_validate.py |
| シャーディングビルド / マージのワークフロー | docs/source/write.md(「データセットのマージ」)、docs/source/faq.md |
| トラック再アラインメントの内部 | python/genvarloader/_dataset/_tracks.py、_reconstruct.py |
| 挿入フィルの内部 | python/genvarloader/_dataset/_insertion_fill.py |
| SVAR 逆参照 / マイグレーション | python/genvarloader/_dataset/_svar_link.py |
.svar2 逆参照 / 読み取りバウンドの配線 | python/genvarloader/_dataset/_svar2_link.py、_svar2_haps.py |
.svar2 スパース範囲キャッシュのレイアウト(書き込み/読み取り/concat) | python/genvarloader/_dataset/_svar2_ranges.py |
| フォーマット 1.x → 2.0 マイグレーションの内部 | python/genvarloader/_dataset/_migrate.py |
| フラットバッファの ragged コンテナ | python/genvarloader/_flat.py |
| フラットバリアント + アレル型 | python/genvarloader/_dataset/_flat_variants.py |
| フランク取得 + トークン化 + ウィンドウ | python/genvarloader/_dataset/_flat_flanks.py |
よくある落とし穴
- 2.0 より前のデータセットは、開く前に一度マイグレーションする必要があります。
Dataset.openは、genvarloader < 2.0 (またはバージョンなし) で書き込まれたあらゆるデータセットをValueErrorで拒否し、gvl.migrate(path)を指し示します。これを一度実行してください (その場で、冪等、クラッシュセーフ)。より新しいメジャーバージョンで書き込まれたデータセットは、別のValueErrorを発生させ、genvarloader のアップグレードを求めます。なお、gvl.migrate(フォーマットのアップグレード) はgvl.migrate_svar_link(SVAR シンボリックリンクレイアウトのアップグレード) とは異なります。 gvl.updateは開いているデータセットをホットリロードしません。gvl.updateの実行前に開かれたDatasetインスタンスは、新しいトラックを認識しません。反映させるにはデータセットを再度開いてください。更新自体は、リーダーがアクティブな間に実行しても安全です。各トラックはアトミックに公開されるため、リーダーが書き込み途中のトラックを目にすることはありません。Dataset.write_annot_tracksは削除されました。 代わりにgvl.update(dataset, annot_tracks={"name": source})を使用するか、作成時にgvl.writeにannot_tracks=を渡してください。gvl.Tableはコアの公開 API です。 追加のインストールは不要です。Rust の COITrees オーバーラップエンジンを使用し、CI でカバーされています。gvl.Tableとしてインポートしてください (トップレベルのパッケージから再エクスポートされています)。- シンボリック / ブレークエンドバリアントはスキップされず、拒否されます。
gvl.writeの前にそれらを除去してください — 例えばbcftools view -e 'ALT~"<" || ALT~"\["'(SV とブレークエンドを削除)、またはfilter=genoray.exprs.is_biallelic & ~genoray.exprs.is_symbolic & ~genoray.exprs.is_breakendを指定して genoray リーダーを構築します。SVAR 入力は、あらかじめフィルタリングされたソースから構築する必要があります。gvl はマテリアライズされた.svarを検証できますが、再フィルタリングはできないためです。.svar2の場合、同じバリアントはgvl.write時ではなく.svar2変換時に上流で (genoray によって) 拒否されます — ストアフォーマットはそれらをそもそも表現できません。 .svar2には Phase-1 の未サポートの組み合わせマトリクスがあります。min_af/max_af、annotatedハプロタイプ、VarWindowOpt(ref="allele")、非ハプロタイプ/トラック出力でのスプライシングまたはvar_filter="exonic"、逆相補または固定長のハプロタイプ再アラインメントトラック、ジッター付きのvariants/variant-windows出力 (書き込み時のmax_jitter>0または読み取り時のjitter>0)、書き込み時のextend_to_length=Falseはすべて、.svar2ベースのデータセットでは暗黙に誤計算するのではなくNotImplementedErrorを発生させます。プレーンなハプロタイプは、スプライシング、エクソンフィルタリング、ネガティブ鎖の逆相補をサポートします。with_seqs("variant-windows")、unphased_union、var_fieldsで選択されたストア INFO/FORMAT フィールド ("variants"と"variant-windows"の両方)、およびマルチコンティグのFlankSampleトラック充填 (issue #267) も.svar2でサポートされています。上記の「.svar2— 読み取りバウンドのスパースバリアントフォーマット」を参照してください。.svar2のvariants/variant-windowsの ALT バイトは、純粋な欠失の場合に.svarと異なります。.svarは VCF アンカーベースを保持します (GTA>Gに対してb"G")。.svar2はアトマイズされた空の ALT (b"") をデコードします。再構築されたハプロタイプはどちらの場合もバイト単位で同一です。ref_windowもバイト単位で同一です — 純粋な欠失レコードで異なるのは生の ALT/alt_windowバイトのみです。- ジェノタイプのみのデータセットを
reference=なしで開くと、"haplotypes"ではなく"variants"ビュー (RaggedVariants) がデフォルトになります。参照なしで利用できるのは"variants"のみです。参照が提供されていない場合、with_seqs("haplotypes" | "annotated" | "reference")はValueErrorを発生させます。 with_insertion_fillは、データセットでハプロタイプとトラックの両方がアクティブでない限り発生します。min_af/max_afは.svarのみでサポートされています。SVAR ベースでないデータセット (プレーンな BCF/PGEN) はRuntimeErrorを発生させます。.svar2ベースのデータセットは特にNotImplementedErrorを発生させます。with_len(L)にはL + 2·jitter ≤ min(region_length) + 2·max_jitterが必要です —write時にmax_jitterを適切に設定してください。- トラックは一意の
.nameを持つ必要があります。オンディスクのレイアウトはintervals/<name>/です。 - BED の
strandが.の場合は+として扱われます。逆相補はrc_neg=True(デフォルト) かつstrand == "-"のときに自動的に行われます。 - スプライシングはエクソンのフラットな BED に対する読み取り時の設定です —
gvl.writeの前にエクソンを事前に連結しないでください。 - 書き込み時の
extend_to_length=Falseは、欠失が存在する場合に BED 領域より短いハプロタイプを生成します。ダウンストリームのコードは<領域長を許容する必要があります。.svar2バリアントソースにはオプションではありません —gvl.write(..., variants=<.svar2>, extend_to_length=False)はNotImplementedErrorを発生させます。 - 期待した
RaggedVariants出力にdosageフィールドがない場合は、var_fieldsを確認してください — ディスク上にdosages.npyが存在していても、dosageは明示的に要求する必要があります。 - アレルフィールドはバリアントごとにインデックスされ、
seqpro>=0.22が必要です。rv.alt[b][h]はバリアントごとに 1 つのアレルを返し、rv.start[b][h]と一致します。seqpro<0.22では、グループのアレルが 1 つのbytesとして連結されて返されていました — これは SNP のみのデータでは見えない不一致であり (すべてのアレルが 1 バイトなのでカウントが一致します)、ウィンドウにインデルが入って初めて現れます。gvl はseqpro>=0.22を要求します。連結された塊が見える場合は、まずインストールされている seqpro のバージョンを確認してください。 FlatRagged/FlatVariantsのオフセットは int64 です。PyTorch のネストテンソルは int32 オフセットを要求します —torch.nested.narrowに渡す前に.astype(np.int32)またはtensor.to(torch.int32)でキャストしてください。kind="intervals"は再アラインメントできません。バリアント対応の seq モード (haplotypes/annotated/variants/variant-windows) と組み合わせると、with_settings(realign_tracks=False)でない限り発生します。(破壊的変更:haplotypes+intervalsは以前、デフォルトで再アラインメントされていない intervals を暗黙に返していました。)with_insertion_fillはrealign_tracks=Falseのときに発生します。with_seqs("variant-windows")にはVarWindowOptの第 2 引数、with_output_format("flat")、および参照ゲノムが必要です。"ragged"モードでのクエリは発生します。with_settingsからフランク設定を継承しません。- フラットなライドアロングフランクトークンにはトラックを無効化する必要があります。
FlatVariants.flank_tokens("variants"出力へのライドアロング) は純粋なフラットバリアントチャネルでのみ生成されます — トラックがアクティブな場合、variants 出力はラギッドなRaggedVariantsにフォールバックします (flank_tokensはありません)。ライドアロングにはwith_tracks(False)を呼び出してください。"variant-windows"はwith_settings(realign_tracks=False)を介してトラックと組み合わせることができます (トラックはウィンドウ出力と並んで参照座標で返されます)。 - フランクトークン (
FlatVariants.flank_tokens) とバリアントウィンドウ (FlatVariantWindows) は参照指向です —rc_neg=Trueであっても逆相補されません。RC されるのはFlatVariants/RaggedVariantsの alt/ref アレルフィールドのみです (そのスカラーフィールド、フランクトークン、ウィンドウは RC されません)。 - トークンの dtype は、最大トークン ID ≤ 255 の場合は
uint8、それ以外はint32です。オフセットはint64です。 VarWindowOpt(ref="allele")(ベアアレルモード) にはディスク上の REF アレルが必要です。FlatVariantsへのflank_lengthライドアロングには、token_alphabetとunknown_tokenを同じまたは以前のwith_settings呼び出しで一緒に設定する必要があります。dummy_variantパディングは"variants"と"variant-windows"の両方の出力に適用されます。dummy_variant=<DummyVariant>を設定してから他の kind ("haplotypes"、"annotated"、"reference"、または seqs なし) でインデックスするとValueErrorを発生させます。トークンフィールド (flank_tokens、ref_window/alt_window、ベアのref/alt) の場合、ダミー充填はすべてunknown_tokenです —DummyVariant.ref/.altバイトはダミーアレルのバイト長を設定するだけで、トークン値は設定しません。サポートされていない出力 kind でのdummy_variant=Falseは暗黙に無視されます。b"N"でないDummyVariant.alt(または.ref) は、実際のバリアントアレルとまったく同様に、ネガティブ鎖領域で逆相補されます。デフォルトのb"N"は rc 不変です。鎖に中立なセンチネルが必要な場合はこれを使用してください。unphased_union=True+with_seqs("haplotypes")/with_seqs("annotated")は発生します —unphased_unionは"variants"/"variant-windows"出力にのみ適用されます。.svar2のレンジキャッシュの書き込み時アキュムレータはmax_memで制限されません。.svar2ソースを指定したgvl.writeは、永続的なgenotypes/svar2_ranges/キャッシュをスパースな リージョン CSR テーブルとして構築します — 空でない(region, sample, ploid)ウィンドウあたり 28 バイト、All of Us chr22 グリッドで約 504 MB、コホート規模では小さい (format.mdを参照)。残るメモリの驚きは書き込み時です:max_memは genoray のチャンクストリームを制限しますが、コンティグごとのエントリアキュムレータは制限しません。これは最大のコンティグでエントリあたりおよそ 60 バイトでピークに達します — チャンクごとの(region int32, cell int32, 24-byte entry)ブロックとマージされた(cell, entry)出力が同時に存在します (chr22 で約 1.1 GB、最大のコンティグで 1 桁台前半の GB)。Dataset.samplesは数値ではなく辞書順にソートされます。 桁数が混在する整数のような ID を持つコホートは、フェノタイプテーブルが通常持つ数値ソートとは異なる順序になります (文字列として"1000" < "999")。両者の間の位置ベースの結合は暗黙に誤りになります。サンプル名で結合してください。gvl.concatには 1 つの共有バリアントソースと少なくとも 2 つの入力が必要です。 バリアントソースの不一致 (バックエンドの種類だけでなくフィンガープリントでチェック)、サンプルセット/順序が異なるaxis="regions"、またはリージョンが異なる、もしくはサンプルが重複するaxis="samples"はすべて、バイトが移動する前にValueErrorを発生させます。マージされたデータセットのほぼ全体のサイズをシーケンシャル IO 速度で移動します — 日常的なステップではありません。
このスキルのメンテナンス
PR がパブリック API(python/genvarloader/__init__.py の __all__ に含まれるもの、または gvl.write、Dataset.open、もしくは任意の Dataset.with_* メソッドの docstring/シグネチャ)を変更する場合は常に、作成者はこの SKILL.md も更新する必要があります。新しいパブリックシンボルの追加、シンボルの削除、引数の名前変更、デフォルト値の変更、新しい出力モードはすべて対象です。CLAUDE.md はこれをコントリビューションチェックリストの一部として義務付けています。