Methylation (bisulfite)
The tutorials target the JBrowse v5 beta, and the v4.3.0 release
on the download page lacks some of what they show. To install the
beta of JBrowse Web, run npm install -g @jbrowse/cli@next, then
jbrowse create jbrowse2 --branch v5.0.0-beta.20. Desktop beta builds for Linux and
macOS are on the releases page;
the Windows build waits on code signing.
Whole-genome bisulfite sequencing (WGBS) and enzymatic methyl sequencing (EM-seq) measure DNA methylation with short reads. JBrowse computes each call from the C→T changes in a read against the reference as it draws, so an aligned BAM is all it needs. In plants, gene bodies and transposons differ in which cytosine contexts are methylated. With an Arabidopsis thaliana WGBS run we:
- align the reads with bwameth and load the BAM as an alignments track on the TAIR10 hub assembly
- load MethylDackel's per-context fractions as a multi-quantitative track
- color each read's cytosines with Color by → Bisulfite / EM-seq, one context at a time
- pin the CpG, CHG and CHH contexts in three copies of the reads track, beside gene and RepeatMasker tracks, to compare a gene with a transposon
Prerequisites
- the NCBI
datasetsCLI, andwget - Trim Galore (with cutadapt)
- bwameth
- samtools
node, for the JBrowse CLI- MethylDackel, for the conversion-rate check and the optional aggregate track
- UCSC's
bedGraphToBigWig, for the optional aggregate track only
# Debian/Ubuntu
sudo apt install samtools tabix nodejs
# or conda, which has every tool above
conda install -c bioconda -c conda-forge samtools htslib nodejs \
ucsc-bedgraphtobigwig ncbi-datasets-cli
# or Linux x86_64 binaries for the tools apt lacks
wget -P ~/.local/bin \
https://hgdownload.soe.ucsc.edu/admin/exe/linux.x86_64/bedGraphToBigWig \
https://ftp.ncbi.nlm.nih.gov/pub/datasets/command-line/v2/linux-amd64/datasets \
https://ftp.ncbi.nlm.nih.gov/pub/datasets/command-line/v2/linux-amd64/dataformat
chmod +x ~/.local/bin/bedGraphToBigWig ~/.local/bin/datasets ~/.local/bin/dataformat
# any platform
npm install -g @jbrowse/cli@nextThe data
TAIR10 (RefSeq GCF_000001735.4) and one wild-type Col-0 WGBS run from the
European Nucleotide Archive, DRR029742 (paired-end 150 bp).
The page's commands build local files from these, and the tracks over those read them from disk; every other track reads a hosted copy. The build script fetches everything itself. To produce the BAM, supply your own bisulfite FASTQ and reference.
| What it is | File |
|---|---|
The TAIR10 reference the reads align to, fetched by accession with the datasets CLI | GCF_000001735.4_TAIR10.1/ |
| The WGBS run's paired-end reads | DRR029742/ |
What bisulfite data looks like
A chemical (sodium bisulfite) or enzymatic (APOBEC, in EM-seq) step converts every unmethylated cytosine to uracil, which reads as T, and a methylated cytosine still reads as C. Comparing each read to the reference recovers the methylation: a C→T change means unmethylated, and a retained C means methylated. JBrowse makes that comparison per read as it draws.
Plants methylate in three sequence contexts: CpG, CHG, and CHH (H is A, C, or T). JBrowse colors the reads by one context at a time.
Producing the BAM
The reproduce script trims the reads of
DRR029742 with Trim Galore
and aligns them with bwameth, which C→T
converts reads and reference in silico and runs bwa mem. The BAM keeps the
original read sequences, so the C→T changes are still there for JBrowse to find;
Bismark BAMs work the same way. Trimming and alignment, on any pair of WGBS or
EM-seq FASTQs:
trim_galore --paired R1.fastq.gz R2.fastq.gz
# index once per reference: bwameth aligns against a C->T copy of it
bwameth.py index tair10.fa
# the BAM keeps the original read sequences for JBrowse to compare
bwameth.py --reference tair10.fa -t 8 R1_val_1.fq.gz R2_val_2.fq.gz \
| samtools sort -o arabidopsis_wgbs.bam -
samtools index arabidopsis_wgbs.bambwameth.py index writes the converted reference beside the original, so that
directory has to be writable.
Checking the bisulfite conversion rate
An unconverted cytosine is indistinguishable from a methylated one, so measure the library's conversion rate first. The chloroplast is unmethylated, which makes it the control:
MethylDackel extract --CHH -r NC_000932.1 -o conversion \
tair10.fa arabidopsis_wgbs.bamColumn 4 of conversion_CHH.bedGraph is the methylated percentage at each
cytosine, which on an unmethylated sequence is the fraction the conversion
missed. Modern libraries convert above 99%. An organism with no plastid uses the
library's spike-in, usually unmethylated lambda or pUC19, added to the reference
as an extra contig.
Loading the TAIR10 hub assembly and the WGBS BAM
TAIR10 is a genome hub on genomes.jbrowse.org,
whose config.json holds the 2bit sequence, an alias table and the NCBI RefSeq
genes. The view loads its assembly and gene track from there, and the BAM and
the optional bigWigs go in beside them:
# a GenArk hub's path is its accession cut into threes
curl -fO https://jbrowse.org/hubs/genark/GCF/000/001/735/GCF_000001735.4/config.jsonThe reproduce script keeps the hub's assembly entry
as written, adding tair10 as an alias so a session can still name it that way.
The hub's assembly entry
The excerpt leaves out the entry's UCSC metadata block; the downloaded
config.json has it.
{
"name": "GCF_000001735.4",
"displayName": "thale cress (tair10.1 Columbia 2018)",
"aliases": ["tair10"],
"sequence": {
"type": "ReferenceSequenceTrack",
"trackId": "GCF_000001735.4-ReferenceSequenceTrack",
"adapter": {
"type": "TwoBitAdapter",
"uri": "https://hgdownload.soe.ucsc.edu/hubs/GCF/000/001/735/GCF_000001735.4/GCF_000001735.4.2bit",
"chromSizes": "https://hgdownload.soe.ucsc.edu/hubs/GCF/000/001/735/GCF_000001735.4/GCF_000001735.4.chrom.sizes.txt"
}
},
"refNameAliases": {
"adapter": {
"type": "RefNameAliasAdapter",
"refNameColumnHeaderName": "ucsc",
"uri": "https://hgdownload.soe.ucsc.edu/hubs/GCF/000/001/735/GCF_000001735.4/GCF_000001735.4.chromAlias.txt"
}
},
"geneticCodes": { "NC_000932.1": 11 }
}The 2bit is the same TAIR10.1 sequence the reads were aligned to, and JBrowse
reads each cytosine's context off it. The alias table maps NC_003070.9, 1,
Chr1 and chr1 to one chromosome, so the BAM keeps the RefSeq names bwameth
wrote, and refNameColumnHeaderName makes chr1 the name the view shows.
The BAM goes in beside the hub assembly:
jbrowse add-track arabidopsis_wgbs.bam --assemblyNames GCF_000001735.4 \
--name "Arabidopsis WGBS (bwameth)" --load copyThe displayDefaults in the alignments track config set the context the track
opens on, and the track menu switches it afterwards:
Goes in the tracks array of config.json. See Tracks.
{
"trackId": "arabidopsis_wgbs",
"name": "Arabidopsis WGBS (bwameth)",
"uri": "arabidopsis_wgbs.bam",
"assemblyNames": ["GCF_000001735.4"],
"displayDefaults": {
"pileup": {
"bases": {
"show": true,
"encoding": { "color": "bisulfite" },
"filter": [{ "field": "context", "oneOf": ["CG"] }]
}
}
}
}jbrowse add-track arabidopsis_wgbs.bam \
--trackId arabidopsis_wgbs \
--name "Arabidopsis WGBS (bwameth)" \
--assemblyNames GCF_000001735.4 \
--displayDefaults '{"pileup":{"bases":{"show":true,"encoding":{"color":"bisulfite"},"filter":[{"field":"context","oneOf":["CG"]}]}}}' \
--load copyIn JBrowse Desktop, or in any running JBrowse Web session, open a view on this track’s assembly, then File → Open track..., choose Add track from pasted JSON, and paste:
{
"trackId": "arabidopsis_wgbs",
"name": "Arabidopsis WGBS (bwameth)",
"uri": "arabidopsis_wgbs.bam",
"assemblyNames": ["GCF_000001735.4"],
"displayDefaults": {
"pileup": {
"bases": {
"show": true,
"encoding": { "color": "bisulfite" },
"filter": [{ "field": "context", "oneOf": ["CG"] }]
}
}
}
}arabidopsis_wgbs.bam is relative to a config.json. Replace it with its URL or its path on this computer.
In grammar-of-graphics terms, pileup.bases
is a color channel for each base, here set from the bisulfite field. The
context entry in its filter takes
CG, CHG or CHH, and { "field": "context" } paints every context.
Aggregate methylation per context with MethylDackel
Beside the reads, a per-position fraction summarizes all the reads at each site, and a bigWig of it draws at any zoom. The track is optional, and the reproduce script leaves it out. MethylDackel calls that fraction in all three plant contexts, one bedGraph each, which becomes a bigWig once the header line is dropped and the percentage column kept:
# CpG is emitted always; --CHG --CHH add the two plant contexts.
# -o fixes the output prefix, which the loop below reads back.
MethylDackel extract --CHG --CHH -o arabidopsis_wgbs \
tair10.fa arabidopsis_wgbs.bam
samtools faidx tair10.fa
cut -f1,2 tair10.fa.fai > tair10.chrom.sizes # two columns, not the .fai itself
for ctx in CpG CHG CHH; do
# tail drops MethylDackel's track line; cut keeps the percentage column
tail -n +2 arabidopsis_wgbs_${ctx}.bedGraph | cut -f1-4 |
sort -k1,1 -k2,2n > ${ctx}.bg
bedGraphToBigWig ${ctx}.bg tair10.chrom.sizes arabidopsis_wgbs_${ctx}.bw
doneA MultiQuantitativeTrack with a subadapter per context draws the three bigWigs
as labeled rows, the Aggregate methylation track in the figure below.
Goes in the tracks array of config.json. See Tracks.
{
"type": "MultiQuantitativeTrack",
"trackId": "arabidopsis_wgbs_methyldackel",
"name": "Aggregate methylation (MethylDackel)",
"assemblyNames": ["GCF_000001735.4"],
"adapter": {
"type": "MultiWiggleAdapter",
"subadapters": [
{
"type": "BigWigAdapter",
"name": "CpG",
"color": "#d62728",
"uri": "arabidopsis_wgbs_CpG.bw"
},
{
"type": "BigWigAdapter",
"name": "CHG",
"color": "#ff7f0e",
"uri": "arabidopsis_wgbs_CHG.bw"
},
{
"type": "BigWigAdapter",
"name": "CHH",
"color": "#1f77b4",
"uri": "arabidopsis_wgbs_CHH.bw"
}
]
},
"displayDefaults": {
"mark": "bar",
"encoding": {
"y": {
"scale": { "domainMin": 0, "domainMax": 100 },
"axis": { "title": "% methylated" }
}
}
}
}jbrowse add-track-json '{
"type": "MultiQuantitativeTrack",
"trackId": "arabidopsis_wgbs_methyldackel",
"name": "Aggregate methylation (MethylDackel)",
"assemblyNames": ["GCF_000001735.4"],
"adapter": {
"type": "MultiWiggleAdapter",
"subadapters": [
{
"type": "BigWigAdapter",
"name": "CpG",
"color": "#d62728",
"uri": "arabidopsis_wgbs_CpG.bw"
},
{
"type": "BigWigAdapter",
"name": "CHG",
"color": "#ff7f0e",
"uri": "arabidopsis_wgbs_CHG.bw"
},
{
"type": "BigWigAdapter",
"name": "CHH",
"color": "#1f77b4",
"uri": "arabidopsis_wgbs_CHH.bw"
}
]
},
"displayDefaults": {
"mark": "bar",
"encoding": {
"y": {
"scale": { "domainMin": 0, "domainMax": 100 },
"axis": { "title": "% methylated" }
}
}
}
}'In JBrowse Desktop, or in any running JBrowse Web session, open a view on this track’s assembly, then File → Open track..., choose Add track from pasted JSON, and paste:
{
"type": "MultiQuantitativeTrack",
"trackId": "arabidopsis_wgbs_methyldackel",
"name": "Aggregate methylation (MethylDackel)",
"assemblyNames": ["GCF_000001735.4"],
"adapter": {
"type": "MultiWiggleAdapter",
"subadapters": [
{
"type": "BigWigAdapter",
"name": "CpG",
"color": "#d62728",
"uri": "arabidopsis_wgbs_CpG.bw"
},
{
"type": "BigWigAdapter",
"name": "CHG",
"color": "#ff7f0e",
"uri": "arabidopsis_wgbs_CHG.bw"
},
{
"type": "BigWigAdapter",
"name": "CHH",
"color": "#1f77b4",
"uri": "arabidopsis_wgbs_CHH.bw"
}
]
},
"displayDefaults": {
"mark": "bar",
"encoding": {
"y": {
"scale": { "domainMin": 0, "domainMax": 100 },
"axis": { "title": "% methylated" }
}
}
}
}arabidopsis_wgbs_CpG.bw, arabidopsis_wgbs_CHG.bw, arabidopsis_wgbs_CHH.bw are relative to a config.json. Replace each with its URL or its path on this computer.
Coloring the reads by cytosine context
Color by → Bisulfite / EM-seq in the alignments track menu sets
pileup.bases to the bisulfite field, which paints each read's methylated
cytosines red. Two more rows refine it:
- Color by → Cytosine context picks CpG, CHG, CHH or All cytosines
- Color by → Show unmodified in blue also paints converted sites blue, separating an unmethylated cytosine from a position with no cytosine. The figure and clip further down leave it off
Gene body methylation and transposon silencing
Plants run two unrelated methylation programs, and the three contexts distinguish them:
| Program | CpG | CHG | CHH | Effect on the locus |
|---|---|---|---|---|
| Gene body methylation (gbM) | yes | no | no | None obvious, the gene stays transcribed. Depleted at both gene ends |
| Transposon and repeat silencing | yes | yes | yes | Heterochromatin, transcriptionally off |
Red in the CpG context alone is gene body methylation, and red in all three contexts is silencing.
Type chr1:4,398,000-4,412,000 into the location box for a window containing
one of each: the expressed gene AT1G12930 on the left, and a transposon on the
right.
To identify the element on the right, add the RepeatMasker track from the TAIR10
genome hub. It labels the element META1_LTR#LTR/Copia, an LTR retrotransposon.
No RefSeq transcript overlaps it:
Goes in the tracks array of config.json. See Tracks.
{
"type": "FeatureTrack",
"trackId": "tair10_repeatmasker",
"name": "RepeatMasker",
"assemblyNames": ["GCF_000001735.4"],
"adapter": {
"type": "BigBedAdapter",
"uri": "https://hgdownload.soe.ucsc.edu/hubs/GCF/000/001/735/GCF_000001735.4/bbi/GCF_000001735.4_TAIR10.1.rmsk.bb"
}
}jbrowse add-track https://hgdownload.soe.ucsc.edu/hubs/GCF/000/001/735/GCF_000001735.4/bbi/GCF_000001735.4_TAIR10.1.rmsk.bb \
--trackId tair10_repeatmasker \
--name RepeatMasker \
--assemblyNames GCF_000001735.4In JBrowse Desktop, or in any running JBrowse Web session, open a view on this track’s assembly, then File → Open track... and, in Add a track from file or URL, enter:
- Main file:
https://hgdownload.soe.ucsc.edu/hubs/GCF/000/001/735/GCF_000001735.4/bbi/GCF_000001735.4_TAIR10.1.rmsk.bb
Click Next. JBrowse reads the adapter and track type off the file name. Then fill in:
- Track name:
RepeatMasker - Assembly:
GCF_000001735.4
Click Add.
Filter by... in the RepeatMasker track menu takes a filter. Enter
jexl:feature.end-feature.start>1000 to keep repeats longer than 1 kb. The
short simple repeats in the window drop out and the LTR element stays.
The figure below shows the three contexts side by side as three tracks that
share one file and differ in trackId and in the context their
displayDefaults pin. The CHG copy looks like this; the CpG and CHH copies
change the trackId, the name and the context entry:
Goes in the tracks array of config.json. See Tracks.
{
"trackId": "arabidopsis_wgbs_chg",
"name": "Per-read WGBS, CHG context",
"uri": "https://jbrowse.org/demos/bisulfite/arabidopsis_wgbs_bisulfite.cram",
"assemblyNames": ["GCF_000001735.4"],
"displayDefaults": {
"pileup": {
"bases": {
"show": true,
"encoding": { "color": "bisulfite" },
"filter": [{ "field": "context", "oneOf": ["CHG"] }]
}
},
"coverage": { "show": false }
}
}jbrowse add-track https://jbrowse.org/demos/bisulfite/arabidopsis_wgbs_bisulfite.cram \
--trackId arabidopsis_wgbs_chg \
--name "Per-read WGBS, CHG context" \
--assemblyNames GCF_000001735.4 \
--displayDefaults '{"pileup":{"bases":{"show":true,"encoding":{"color":"bisulfite"},"filter":[{"field":"context","oneOf":["CHG"]}]}},"coverage":{"show":false}}'In JBrowse Desktop, or in any running JBrowse Web session, open a view on this track’s assembly, then File → Open track..., choose Add track from pasted JSON, and paste:
{
"trackId": "arabidopsis_wgbs_chg",
"name": "Per-read WGBS, CHG context",
"uri": "https://jbrowse.org/demos/bisulfite/arabidopsis_wgbs_bisulfite.cram",
"assemblyNames": ["GCF_000001735.4"],
"displayDefaults": {
"pileup": {
"bases": {
"show": true,
"encoding": { "color": "bisulfite" },
"filter": [{ "field": "context", "oneOf": ["CHG"] }]
}
},
"coverage": { "show": false }
}
}Reproduce it end to end
The whole pipeline is wrapped in one script,
build_arabidopsis_wgbs.sh.
It:
- downloads the TAIR10 reference and the DRR029742 WGBS run, then trims and aligns them with bwameth
- downloads JBrowse and writes a
config.jsonwith the hub's TAIR10 assembly and RefSeq genes and the pileup pre-colored Bisulfite / CpG, opening on the window above - with MethylDackel on
PATH, prints the conversion rate and the per-context fractions (the aggregate bigWig track is left out either way)
curl -fO https://raw.githubusercontent.com/GMOD/jbrowse-components/main/scripts/build_arabidopsis_wgbs.sh
bash build_arabidopsis_wgbs.sh # builds ./arabidopsis_wgbs_build/jbrowse2
npx --yes serve arabidopsis_wgbs_build/jbrowse2 # then open the printed URLOn Debian/Ubuntu, apt install wget curl samtools covers several
prerequisites; the rest install from the pages linked there.
The alignment step downloads a full WGBS run, so allow time and disk.
See also
- Tutorial: Methylation (long-read)
- User guide: Quantitative track
- User guide: Alignments track
External links
- Methylation (bisulfite) in R, the same analysis written for ggjbrowse
Feedback on this tutorial is welcome: contact us.