Bit-packing for DNA methylation. Arrays and whole genomes in one binary format family, where analysis is bitwise — and so stays fast across a thousandfold of scale, from 28K probes to 29M CpGs.
No reference data is bundled: no coordinates, no feature sets, no example
methylomes. yame fetch opens a browser over the
catalogue — species, then platform or genome build, then its files.
yame fetch
yame fetch • ~/.local/share/yame
TARGET KIND TAG IN STORE
▪ HUMAN
❯ ▾ [*] hg38 genome mixed ▰▱▱▱▱ 5/47
├── ● cpg_nocontig.cr v2 28.9 MB
├── ▸ [ ] KYCG sets v2 ▱▱▱▱▱ 0/32
├── ▸ ✓ data sets v3 ▰▰▰▰▰ 5/5
────────────────────────────────────────
hg38 genome build
Arrows move, / filters by name, source,
collection or title, x takes a row (a folder takes
everything under it) and f fetches. What the store
already holds shows as present and cannot be re-taken.
Files land in a digest-verified store shared by every tool in the suite
— $YAME_DATA_HOME, default
~/.local/share/yame — so what you fetch here
is what KnowYourCG and SeSAMe
find. Everything else on this page runs against it.
The store is laid out the way the tree reads. What you see under a
name is what lands under that name on disk, so hg38/data
in the browser is $YAME_DATA_HOME/hg38/data, and a
genome's knowledgebase simply nests inside it. Which upstream repo published
a directory is a column in fetch -l, not a path
component — one name, whether you are browsing, fetching or looking at
the disk.
What it carries are the row spaces everything else is measured in. Each length is distinct, so the count is the identity — which is what lets -R and -m take a name instead of a path.
row space rows row space rows ───────────────────────────────────────────── hg38 29,401,795 HM450 486,427 mm10 21,867,837 MM285 287,692 mm39 21,889,506 MSA 284,309 EPICv2 937,690 Mammal40 38,607 EPIC 866,553 HM27 27,722
Piped or redirected, fetch prints the catalogue
as TSV instead, so a script never blocks on a keystroke. Naming a target,
filtering it, dry runs and the rest:
yame fetch -h.
Almost everything in practice is one of three kinds of data, and they land in two of the seven formats. One table covers how each is stored and what pack reads to build it.
the data format on disk pack one line per CpG ──────────────────────────────────────────────────────────────────────────────── methylation, M/U counts 3 M/U counts 1-8 B/site -fm M ⇥ U methylation, binarized 6 set+universe 2 bits/row -fd call ⇥ covered a CpG set 6 set+universe 2 bits/row -fd in set ⇥ in universe
pack is the only way in. Input is one row per CpG already in the reference's order — nothing is sorted or matched for you. Columns are tab-separated, and under -fd the first column must be exactly 1 to count as in-set while the second is any nonzero int.
yame fetch -c hg38/data/human_hg38_test.cg
yame fetch hg38/cpg_nocontig.cr # the coordinates, into the store
yame unpack -R hg38 human_hg38_test.cg | awk '$4!=2' | head -5
chr1 659296 659298 1
chr1 779099 779101 0
chr1 795737 795739 1
chr1 933194 933196 0
chr1 958160 958162 1
Format 6 prints one column by default; -f -1 gives set and universe separately, which is what pack -f6 reads back:
yame unpack -f -1 human_hg38_test.cg | awk '$1!="NA"' | head -3
1 1
0 1
1 1
yame unpack -f -1 human_hg38_test.cg > rt.txt
yame pack -f6 rt.txt rt.cg # and back again
Verified byte-identical on the round trip.
Rows are samples, columns are CpGs or windows. The reference is inferred from the row count, so -r alone is enough.
yame fetch -c hg38/data/human_hg38_celltypes.cg
yame fetch hg38/cpg_nocontig.cr # the coordinates, into the store
yame hprint -r chr20:30000000-30001000 human_hg38_celltypes.cg
chr20:30000011-30000862 (10 CpGs)
|.........
30000011
Oligodendrocyte █...██..░█
Pancreas-Beta █.....░█..
Blood-NK ....██░█░█
Blood-Monocytes ....███.░█
-w caps the width — wider regions are window-averaged rather than truncated — and -R alone gives the whole-genome view.
Records concatenate, so a cohort is one file. The .idx beside it maps sample names to offsets, which is what makes them addressable by name.
yame fetch -c hg38/data/human_hg38_celltypes.cg
yame info human_hg38_celltypes.cg | cut -f2-7
Sample Ncol Nrow Format UnitBytes Keys
Oligodendrocyte 4 29401795 6 2 NA
Pancreas-Beta 4 29401795 6 2 NA
Blood-NK 4 29401795 6 2 NA
Blood-Monocytes 4 29401795 6 2 NA
yame chunk -s 500000 human_hg38_celltypes.cg chunks/ # fixed row blocks
yame subset -o two.cg human_hg38_celltypes.cg Blood-NK Blood-Monocytes
yame info human_hg38_celltypes.cg | cut -f2 | tail -n +2 > names.txt
yame split -s names.txt human_hg38_celltypes.cg out_ # one file each
yame index -s names.txt human_hg38_celltypes.cg # rebuild the index
Sample Nrow Format
Blood-NK 29401795 6
Blood-Monocytes 29401795 6
info -1 reports the first record of each file — the cheap way to see what a directory holds:
File Sample Nrow Format
human_hg38_40_celltypes_chr20.cg GSM5652176_Adipocytes-Z000000T7 773477 3
human_hg38_celltypes.cg Oligodendrocyte 29401795 6
human_hg38_immune_mixture.cg 1 29401795 3
human_hg38_test.cg 1 29401795 6
human_hg38_test.truth.cg 1 29401795 6
With no mask, summary describes the file. With one it gives the overlap table — universe, query, mask, overlap, log2 odds ratio, beta, depth. The mask is named, not spelled out: the query's row count says which row space to resolve it in.
yame fetch -c hg38/data/human_hg38_test.cg
yame fetch hg38/KYCG -g CGI # the mask, into the store
yame summary -m CGI human_hg38_test.cg
QFile Query MFile Mask N_univ N_query N_mask N_overlap Log2OddsRatio Beta Depth
human_hg38_test.cg 1 CGI.20220904.cm OpenSea 29000 23857 23534 21149 3.17 0.899 NA
human_hg38_test.cg 1 CGI.20220904.cm Shelf 29000 23857 1224 1076 0.67 0.879 NA
human_hg38_test.cg 1 CGI.20220904.cm Shore 29000 23857 2074 1263 -1.74 0.609 NA
A format 2 mask yields one row per state, so -m ChromHMM tests every chromatin state at once. -b picks the set in the browser instead.
yame fetch -c hg38/data/human_hg38_immune_mixture.cg
yame fetch -c hg38/data/human_hg38_40_celltypes_chr20.cg
yame binarize -t 0.5 -c 3 -o calls.cg human_hg38_immune_mixture.cg # M/U -> set + universe
yame subset -o a.cg human_hg38_40_celltypes_chr20.cg GSM5652176_Adipocytes-Z000000T7
yame subset -o b.cg human_hg38_40_celltypes_chr20.cg GSM5652181_Saphenous-Vein-Endothel-Z000000RM
yame pairwise -H 1 -c 5 -d 0.2 a.cg b.cg # differential, fmt3 -> fmt6
yame rowop -o binasum human_hg38_40_celltypes_chr20.cg pseudobulk.cg # collapse
Sample Nrow Format
1 773477 3
That last one is how pseudobulks are made: subset the cells of a cluster, pipe into rowop.
Two different jobs. mask is deterministic and file-driven — it decides which sites are valid. dsample and perturb are stochastic and seed-driven — they decide how much signal is left.
yame fetch -c hg38/data/human_hg38_test.cg
yame dsample -N 5000 -s 42 -o ds.cg human_hg38_test.cg
Query N_univ N_query Beta
0 5000 4087 0.817
yame perturb -p 0.05 -s 7 -o noisy.cg human_hg38_test.cg
Query N_univ N_query Beta
1 29000 22953 0.791
Set -s. Without a fixed seed neither is reproducible. mask takes its mask as a positional argument, not -m, and both files must have the same row count.
yame fetch -c hg38/KYCG -g blacklist
yame mask -o clean.cg human_hg38_test.cg Blacklist.20220304.cm