Differential transcript usage
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.17. Desktop beta builds are coming soon.
Differential transcript usage tests whether a gene changes which of its isoforms it expresses between two conditions, here skeletal muscle and liver. We:
- run the test with satuRn, a Bioconductor package, on ENCODE quantifications and write each transcript's statistic into the GFF3 attribute column
- load the GFF3 as a gene track
- color each isoform by that attribute
Prerequisites
- a JBrowse to open the finished GFF3 and coverage tracks in: Desktop takes a local file by path, Web through Add track
curlpython3- htslib (
bgzip,tabix) - R with satuRn, SummarizedExperiment, edgeR and limma, all Bioconductor
# Debian/Ubuntu
sudo apt install tabix
# or conda, which has every tool above
conda install -c bioconda -c conda-forge htslibThe data
ENCODE's ENTEx panel, four skeletal-muscle and four liver donors, quantified with RSEM against GENCODE v29.
You don't need these files to follow the page: the track configs below read the hosted results. The build script fetches them to rebuild those results. The test step takes any transcript-by-sample count matrix with a sample table and a transcript-to-gene table.
| What it is | File |
|---|---|
| Eight RSEM per-transcript quantification tables, the four muscle donors then the four liver donors: , , , , , , | ENCFF353NZM.tsv ENCFF172SLW.tsv ENCFF140GJI.tsv ENCFF576DOG.tsv ENCFF996LRE.tsv ENCFF641ADT.tsv ENCFF392VYD.tsv ENCFF383KWZ.tsv |
| The GENCODE v29 annotation those quantifications were made against | gencode.v29.annotation.gff3.gz |
Read by URL (no download needed)
| What it is | File |
|---|---|
| The four coverage bigWigs the demo's track config loads, one donor per tissue, plus and minus strand: , , | ENCFF007ZBY.bigWig ENCFF518WGP.bigWig ENCFF565QRM.bigWig ENCFF253OSP.bigWig |
Building the GFF3
The build takes the ENCODE quantifications to a colorable GFF3 in three steps, and one script runs all three.
Build the matrices. The script downloads the eight RSEM tables listed above, with the accessions written into it, and writes a count matrix, which feeds the model, and a TPM matrix, which feeds the effect size.
Test usage. satuRn fits a quasi-binomial model to each transcript's share of its gene's reads and tests that share between the two tissues. It takes three inputs:
cnt, a transcript-by-sample count matrixcoldata, a table with onetissuerow per sampletxinfo, a table with anisoform_idand agene_idfor each transcript
The test runs on them:
# after filterByExpr, any gene left with one isoform goes too: usage is a
# within-gene proportion, so a lone isoform is always 100%
keep <- edgeR::filterByExpr(cnt, group = coldata$tissue)
cnt <- cnt[keep, ]
txinfo <- txinfo[rownames(cnt), ]
multi <- names(which(table(txinfo$gene_id) > 1))
txinfo <- txinfo[txinfo$gene_id %in% multi, ]
cnt <- cnt[txinfo$isoform_id, ]
# rowData has to carry isoform_id and gene_id: satuRn reads each transcript's
# gene from there, since usage is a share of the gene's reads
se <- SummarizedExperiment(
assays = list(counts = cnt),
colData = coldata,
rowData = txinfo
)
# the formula names the colData column holding the groups. 0 + tissue drops the
# intercept, so each tissue gets its own coefficient and the contrast below is
# the difference between two of them
se <- satuRn::fitDTU(object = se, formula = ~ 0 + tissue, parallel = FALSE)
design <- model.matrix(~ 0 + tissue, data = coldata)
colnames(design) <- levels(factor(coldata$tissue))
L <- limma::makeContrasts(muscle_vs_liver = muscle - liver, levels = design)
# sort = FALSE leaves the result rows in the order the assay had them, which is
# what lets the isoform fractions be indexed straight into the result
se <- satuRn::testDTU(object = se, contrasts = L, sort = FALSE)
res <- rowData(se)[["fitDTUResult_muscle_vs_liver"]]res holds, per transcript, the p-value, the regular and empirical FDRs and the
model estimates. The script computes each transcript's isoform fraction, its
share of the gene's expression, from the TPM matrix.1
Write the statistics into GENCODE. The annotation has to be the release the quantifications were made against:
- RSEM names each transcript with its version (
ENST00000356708.11), and GENCODE raises that version whenever it revises the transcript. - Joining against a later release drops every transcript revised since, with no error.
- ENCODE lists the release on each quantification's file page as its genome
annotation (
V29for all eight here).
A transcript is called when its regular FDR and its |ΔIF| pass the cutoffs in the code below. The script keeps each gene with a called transcript that is meaningfully expressed, since a fraction can swing widely on a handful of reads, and appends each transcript's numbers to its attribute column in the GENCODE v29 GFF3.
To do the same join over your own results, write results.tsv with one row per
transcript and the columns isoform_id, regular_FDR and dIF (the
isoform-fraction change). This version keeps every GENCODE row and appends:
dif,fdr,dtuanddif_calledto each transcript rowdtu_transcriptsanddtu_top_difto the gene row of each gene with a called transcript
The track reads those keys:
import csv
import gzip
# satuRn writes NA for a transcript it could not fit
stats = {r['isoform_id']: r
for r in csv.DictReader(open('results.tsv'), delimiter='\t')
if 'NA' not in (r['dIF'], r['regular_FDR'])}
genes = {}
called = {}
records = []
with gzip.open('gencode.v29.annotation.gff3.gz', 'rt') as fh:
for line in fh:
if line.startswith('#'):
continue
cols = line.rstrip('\n').split('\t')
d = dict(kv.split('=', 1) for kv in cols[8].split(';') if '=' in kv)
if cols[2] == 'gene':
genes[d['ID']] = cols
elif cols[2] == 'transcript':
r = stats.get(d['transcript_id'])
if r:
dif, fdr = float(r['dIF']), float(r['regular_FDR'])
direction = 'ns'
if fdr < 0.05 and abs(dif) > 0.1:
direction = 'muscle' if dif > 0 else 'liver'
cols[8] += f';dif={dif:.3f};fdr={fdr:.3g};dtu={direction}'
if direction != 'ns':
cols[8] += f';dif_called={dif:.3f}'
called.setdefault(d['Parent'], []).append(dif)
records.append((cols[0], int(cols[3]), int(cols[4]), cols))
for gene_id, difs in called.items():
top = max(difs, key=abs)
genes[gene_id][8] += f';dtu_transcripts={len(difs)};dtu_top_dif={top:.3f}'
records.sort(key=lambda r: r[:3])
with open('dtu_muscle_vs_liver.gff3', 'w') as out:
out.write('##gff-version 3\n')
for _, _, _, cols in records:
out.write('\t'.join(cols) + '\n')The rows come out in coordinate order, so indexing is the ordinary pair:
bgzip -f dtu_muscle_vs_liver.gff3
tabix -f -p gff dtu_muscle_vs_liver.gff3.gzThe statistics in the attribute column
The track reads each transcript's statistics from the attribute column. A transcript row from the finished file, wrapped:
chr10 HAVANA transcript 7788129 7807815 . + .
ID=ENST00000356708.11;Parent=ENSG00000165629.19;gene_name=ATP5F1C;
transcript_name=ATP5F1C-202;...;
dif=-0.299;fdr=0.0022;if_muscle=0.075;if_liver=0.375;
tpm_muscle=10.03;tpm_liver=28.88;dtu=liver;dif_called=-0.299The transcript statistics sit on the transcript row, and the exons, CDS and UTRs
take the transcript value. The gene row has two more keys, which the track's
mouseover reads:
dtu_transcripts, the count of called isoformsdtu_top_dif, the largest ΔIF among them
The keys are lowercase because the GFF parser lowercases them, so a color field
named dIF reads nothing and paints every transcript grey.
dtu is muscle, liver or ns, as the script above calls it. dif_called
is dif on the called transcripts and absent on the rest, so a transcript the
test could not separate has no value to color and stays grey.
Loading GRCh38
GENCODE v29 is a GRCh38 annotation and the coverage is on GRCh38, so we load the hg38 assembly before either track.
Goes in the assemblies array of config.json. See Assemblies.
{
"name": "hg38",
"uri": "https://jbrowse.org/genomes/GRCh38/fasta/hg38.prefix.fa.gz",
"refNameAliases": {
"uri": "https://s3.amazonaws.com/jbrowse.org/genomes/GRCh38/hg38_aliases.txt"
},
"cytobands": "https://jbrowse.org/genomes/GRCh38/cytoBand.txt"
}jbrowse add-assembly https://jbrowse.org/genomes/GRCh38/fasta/hg38.prefix.fa.gz \
--name hg38 \
--refNameAliases https://s3.amazonaws.com/jbrowse.org/genomes/GRCh38/hg38_aliases.txt \
--config '{"cytobands":"https://jbrowse.org/genomes/GRCh38/cytoBand.txt"}'hg38 is one of the genomes JBrowse Desktop hosts, with gene tracks already set up: on the start screen click Show all available genomes and pick it. To load the files of this config instead:
In JBrowse Desktop, Open new genome on the start screen (or File → Open genome... in a session), then Open from a URL and paste, one per line:
https://jbrowse.org/genomes/GRCh38/fasta/hg38.prefix.fa.gz
https://jbrowse.org/genomes/GRCh38/fasta/hg38.prefix.fa.gz.fai
https://jbrowse.org/genomes/GRCh38/fasta/hg38.prefix.fa.gz.gziJBrowse reads the format off the file name. Then fill in:
- Genome name:
hg38 - refName aliases (under More options):
https://s3.amazonaws.com/jbrowse.org/genomes/GRCh38/hg38_aliases.txt - cytobands (under More options):
https://jbrowse.org/genomes/GRCh38/cytoBand.txt
Coloring each isoform by its usage change
In grammar-of-graphics terms,
encoding.color is a color scale: its field, dif_called (a called
transcript's isoform-fraction change), goes through the threshold cuts in
scale.domain to the colors in scale.range, liver-preferred below zero and
muscle-preferred above. A value on a cut takes the interval above it.
- The key lists every interval under the
legend.title, plus a(no value)row for uncalled transcripts. - A UTR follows
encoding.colorunlessutrColoris set. - Clicking an isoform opens its numbers in the details panel.
Goes in the tracks array of config.json. See Tracks.
{
"trackId": "dtu_muscle_vs_liver",
"name": "Transcript usage: skeletal muscle vs liver (satuRn)",
"uri": "https://jbrowse.org/demos/dtu/dtu_muscle_vs_liver.gff3.gz",
"assemblyNames": ["hg38"],
"displayDefaults": {
"subfeatureLabels": "below",
"encoding": {
"color": {
"field": "dif_called",
"scale": {
"type": "threshold",
"domain": [-0.6, -0.3, 0, 0.3, 0.6],
"range": [
"#124f95",
"#2370cc",
"#6394d5",
"#d5716a",
"#c63335",
"#901e21"
],
"names": [
"liver, below -0.6",
"liver, -0.6 to -0.3",
"liver, -0.3 to 0",
"muscle, 0 to 0.3",
"muscle, 0.3 to 0.6",
"muscle, 0.6 and above"
]
},
"legend": { "title": "ΔIF, muscle - liver" }
}
},
"labels": {
"name": "jexl:feature.transcript_name||feature.gene_name||feature.name||feature.id"
},
"mouseover": "jexl:feature.gene_name+': '+feature.dtu_transcripts+' isoform(s) with a usage shift, largest ΔIF '+feature.dtu_top_dif"
}
}jbrowse add-track https://jbrowse.org/demos/dtu/dtu_muscle_vs_liver.gff3.gz \
--trackId dtu_muscle_vs_liver \
--name "Transcript usage: skeletal muscle vs liver (satuRn)" \
--assemblyNames hg38 \
--displayDefaults "{\"subfeatureLabels\":\"below\",\"encoding\":{\"color\":{\"field\":\"dif_called\",\"scale\":{\"type\":\"threshold\",\"domain\":[-0.6,-0.3,0,0.3,0.6],\"range\":[\"#124f95\",\"#2370cc\",\"#6394d5\",\"#d5716a\",\"#c63335\",\"#901e21\"],\"names\":[\"liver, below -0.6\",\"liver, -0.6 to -0.3\",\"liver, -0.3 to 0\",\"muscle, 0 to 0.3\",\"muscle, 0.3 to 0.6\",\"muscle, 0.6 and above\"]},\"legend\":{\"title\":\"ΔIF, muscle - liver\"}}},\"labels\":{\"name\":\"jexl:feature.transcript_name||feature.gene_name||feature.name||feature.id\"},\"mouseover\":\"jexl:feature.gene_name+': '+feature.dtu_transcripts+' isoform(s) with a usage shift, largest ΔIF '+feature.dtu_top_dif\"}"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": "dtu_muscle_vs_liver",
"name": "Transcript usage: skeletal muscle vs liver (satuRn)",
"uri": "https://jbrowse.org/demos/dtu/dtu_muscle_vs_liver.gff3.gz",
"assemblyNames": ["hg38"],
"displayDefaults": {
"subfeatureLabels": "below",
"encoding": {
"color": {
"field": "dif_called",
"scale": {
"type": "threshold",
"domain": [-0.6, -0.3, 0, 0.3, 0.6],
"range": [
"#124f95",
"#2370cc",
"#6394d5",
"#d5716a",
"#c63335",
"#901e21"
],
"names": [
"liver, below -0.6",
"liver, -0.6 to -0.3",
"liver, -0.3 to 0",
"muscle, 0 to 0.3",
"muscle, 0.3 to 0.6",
"muscle, 0.6 and above"
]
},
"legend": { "title": "ΔIF, muscle - liver" }
}
},
"labels": {
"name": "jexl:feature.transcript_name||feature.gene_name||feature.name||feature.id"
},
"mouseover": "jexl:feature.gene_name+': '+feature.dtu_transcripts+' isoform(s) with a usage shift, largest ΔIF '+feature.dtu_top_dif"
}
}Open this track in JBrowse Web ↗
Needs JBrowse Desktop 5.0 or newer. If nothing opens, copy the link and paste it into Desktop's Open JBrowse Web link..., on the start screen or under File → Session.
https://jbrowse.org/code/jb2/main/?config=https%3A%2F%2Fjbrowse.org%2Fucsc%2Fhg38%2Fconfig.json&session=spec-%7B%22sessionTracks%22%3A%5B%7B%22trackId%22%3A%22dtu_muscle_vs_liver%22%2C%22name%22%3A%22Transcript+usage%3A+skeletal+muscle+vs+liver+%28satuRn%29%22%2C%22uri%22%3A%22https%3A%2F%2Fjbrowse.org%2Fdemos%2Fdtu%2Fdtu_muscle_vs_liver.gff3.gz%22%2C%22assemblyNames%22%3A%5B%22hg38%22%5D%2C%22displayDefaults%22%3A%7B%22subfeatureLabels%22%3A%22below%22%2C%22encoding%22%3A%7B%22color%22%3A%7B%22field%22%3A%22dif_called%22%2C%22scale%22%3A%7B%22type%22%3A%22threshold%22%2C%22domain%22%3A%5B-0.6%2C-0.3%2C0%2C0.3%2C0.6%5D%2C%22range%22%3A%5B%22%23124f95%22%2C%22%232370cc%22%2C%22%236394d5%22%2C%22%23d5716a%22%2C%22%23c63335%22%2C%22%23901e21%22%5D%2C%22names%22%3A%5B%22liver%2C+below+-0.6%22%2C%22liver%2C+-0.6+to+-0.3%22%2C%22liver%2C+-0.3+to+0%22%2C%22muscle%2C+0+to+0.3%22%2C%22muscle%2C+0.3+to+0.6%22%2C%22muscle%2C+0.6+and+above%22%5D%7D%2C%22legend%22%3A%7B%22title%22%3A%22%CE%94IF%2C+muscle+-+liver%22%7D%7D%7D%2C%22labels%22%3A%7B%22name%22%3A%22jexl%3Afeature.transcript_name%7C%7Cfeature.gene_name%7C%7Cfeature.name%7C%7Cfeature.id%22%7D%2C%22mouseover%22%3A%22jexl%3Afeature.gene_name%2B%27%3A+%27%2Bfeature.dtu_transcripts%2B%27+isoform%28s%29+with+a+usage+shift%2C+largest+%CE%94IF+%27%2Bfeature.dtu_top_dif%22%7D%7D%5D%2C%22views%22%3A%5B%7B%22type%22%3A%22LinearGenomeView%22%2C%22assembly%22%3A%22hg38%22%2C%22loc%22%3A%22chr10%3A7%2C787%2C600-7%2C812%2C400%22%2C%22tracks%22%3A%5B%22dtu_muscle_vs_liver%22%5D%7D%5D%7D&sessionName=JBrowse+docs%3A+Transcript+usage%3A+skeletal+muscle+vs+liver+%28satuRn%29Add the four coverage tracks below and open them with the transcript track at
chr10:7,787,600-7,812,400, the whole of ATP5F1C, an ATP synthase subunit:
- The gene is on the plus strand, so the two plus-strand tracks hold its reads.
- satuRn used no genomic coordinates, so the coverage is an independent check on the color.
Each coverage track scales to its own peak by default. To compare the tissues by height, choose Y axis... → Share axis with on one track and tick the other; the two then share one axis that follows the view. In a config, each track names the same group:
Goes in the tracks array of config.json. See Tracks.
{
"trackId": "liver_plus",
"name": "Liver RNA-seq, + strand (ENCSR135IAL)",
"uri": "https://jbrowse.org/demos/dtu/ENCFF565QRM.liver.plus.bigWig",
"assemblyNames": ["hg38"],
"displayDefaults": {
"encoding": { "y": { "scale": { "group": "coverage" } } }
}
}jbrowse add-track https://jbrowse.org/demos/dtu/ENCFF565QRM.liver.plus.bigWig \
--trackId liver_plus \
--name "Liver RNA-seq, + strand (ENCSR135IAL)" \
--assemblyNames hg38 \
--displayDefaults '{"encoding":{"y":{"scale":{"group":"coverage"}}}}'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": "liver_plus",
"name": "Liver RNA-seq, + strand (ENCSR135IAL)",
"uri": "https://jbrowse.org/demos/dtu/ENCFF565QRM.liver.plus.bigWig",
"assemblyNames": ["hg38"],
"displayDefaults": {
"encoding": { "y": { "scale": { "group": "coverage" } } }
}
}Open this track in JBrowse Web ↗
Needs JBrowse Desktop 5.0 or newer. If nothing opens, copy the link and paste it into Desktop's Open JBrowse Web link..., on the start screen or under File → Session.
https://jbrowse.org/code/jb2/main/?config=https%3A%2F%2Fjbrowse.org%2Fucsc%2Fhg38%2Fconfig.json&session=spec-%7B%22sessionTracks%22%3A%5B%7B%22trackId%22%3A%22liver_plus%22%2C%22name%22%3A%22Liver+RNA-seq%2C+%2B+strand+%28ENCSR135IAL%29%22%2C%22uri%22%3A%22https%3A%2F%2Fjbrowse.org%2Fdemos%2Fdtu%2FENCFF565QRM.liver.plus.bigWig%22%2C%22assemblyNames%22%3A%5B%22hg38%22%5D%2C%22displayDefaults%22%3A%7B%22encoding%22%3A%7B%22y%22%3A%7B%22scale%22%3A%7B%22group%22%3A%22coverage%22%7D%7D%7D%7D%7D%5D%2C%22views%22%3A%5B%7B%22type%22%3A%22LinearGenomeView%22%2C%22assembly%22%3A%22hg38%22%2C%22loc%22%3A%22chr10%3A7%2C787%2C600-7%2C812%2C400%22%2C%22tracks%22%3A%5B%22liver_plus%22%5D%7D%5D%7D&sessionName=JBrowse+docs%3A+Liver+RNA-seq%2C+%2B+strand+%28ENCSR135IAL%29The other three tracks differ in their id, name and file:
Goes in the tracks array of config.json. See Tracks.
{
"trackId": "liver_minus",
"name": "Liver RNA-seq, - strand (ENCSR135IAL)",
"uri": "https://jbrowse.org/demos/dtu/ENCFF253OSP.liver.minus.bigWig",
"assemblyNames": ["hg38"],
"displayDefaults": {
"encoding": { "y": { "scale": { "group": "coverage" } } }
}
}jbrowse add-track https://jbrowse.org/demos/dtu/ENCFF253OSP.liver.minus.bigWig \
--trackId liver_minus \
--name "Liver RNA-seq, - strand (ENCSR135IAL)" \
--assemblyNames hg38 \
--displayDefaults '{"encoding":{"y":{"scale":{"group":"coverage"}}}}'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": "liver_minus",
"name": "Liver RNA-seq, - strand (ENCSR135IAL)",
"uri": "https://jbrowse.org/demos/dtu/ENCFF253OSP.liver.minus.bigWig",
"assemblyNames": ["hg38"],
"displayDefaults": {
"encoding": { "y": { "scale": { "group": "coverage" } } }
}
}Open this track in JBrowse Web ↗
Needs JBrowse Desktop 5.0 or newer. If nothing opens, copy the link and paste it into Desktop's Open JBrowse Web link..., on the start screen or under File → Session.
https://jbrowse.org/code/jb2/main/?config=https%3A%2F%2Fjbrowse.org%2Fucsc%2Fhg38%2Fconfig.json&session=spec-%7B%22sessionTracks%22%3A%5B%7B%22trackId%22%3A%22liver_minus%22%2C%22name%22%3A%22Liver+RNA-seq%2C+-+strand+%28ENCSR135IAL%29%22%2C%22uri%22%3A%22https%3A%2F%2Fjbrowse.org%2Fdemos%2Fdtu%2FENCFF253OSP.liver.minus.bigWig%22%2C%22assemblyNames%22%3A%5B%22hg38%22%5D%2C%22displayDefaults%22%3A%7B%22encoding%22%3A%7B%22y%22%3A%7B%22scale%22%3A%7B%22group%22%3A%22coverage%22%7D%7D%7D%7D%7D%5D%2C%22views%22%3A%5B%7B%22type%22%3A%22LinearGenomeView%22%2C%22assembly%22%3A%22hg38%22%2C%22loc%22%3A%22chr10%3A7%2C787%2C600-7%2C812%2C400%22%2C%22tracks%22%3A%5B%22liver_minus%22%5D%7D%5D%7D&sessionName=JBrowse+docs%3A+Liver+RNA-seq%2C+-+strand+%28ENCSR135IAL%29Goes in the tracks array of config.json. See Tracks.
{
"trackId": "muscle_plus",
"name": "Skeletal muscle RNA-seq, + strand (ENCSR609NZM)",
"uri": "https://jbrowse.org/demos/dtu/ENCFF007ZBY.muscle.plus.bigWig",
"assemblyNames": ["hg38"],
"displayDefaults": {
"encoding": { "y": { "scale": { "group": "coverage" } } }
}
}jbrowse add-track https://jbrowse.org/demos/dtu/ENCFF007ZBY.muscle.plus.bigWig \
--trackId muscle_plus \
--name "Skeletal muscle RNA-seq, + strand (ENCSR609NZM)" \
--assemblyNames hg38 \
--displayDefaults '{"encoding":{"y":{"scale":{"group":"coverage"}}}}'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": "muscle_plus",
"name": "Skeletal muscle RNA-seq, + strand (ENCSR609NZM)",
"uri": "https://jbrowse.org/demos/dtu/ENCFF007ZBY.muscle.plus.bigWig",
"assemblyNames": ["hg38"],
"displayDefaults": {
"encoding": { "y": { "scale": { "group": "coverage" } } }
}
}Open this track in JBrowse Web ↗
Needs JBrowse Desktop 5.0 or newer. If nothing opens, copy the link and paste it into Desktop's Open JBrowse Web link..., on the start screen or under File → Session.
https://jbrowse.org/code/jb2/main/?config=https%3A%2F%2Fjbrowse.org%2Fucsc%2Fhg38%2Fconfig.json&session=spec-%7B%22sessionTracks%22%3A%5B%7B%22trackId%22%3A%22muscle_plus%22%2C%22name%22%3A%22Skeletal+muscle+RNA-seq%2C+%2B+strand+%28ENCSR609NZM%29%22%2C%22uri%22%3A%22https%3A%2F%2Fjbrowse.org%2Fdemos%2Fdtu%2FENCFF007ZBY.muscle.plus.bigWig%22%2C%22assemblyNames%22%3A%5B%22hg38%22%5D%2C%22displayDefaults%22%3A%7B%22encoding%22%3A%7B%22y%22%3A%7B%22scale%22%3A%7B%22group%22%3A%22coverage%22%7D%7D%7D%7D%7D%5D%2C%22views%22%3A%5B%7B%22type%22%3A%22LinearGenomeView%22%2C%22assembly%22%3A%22hg38%22%2C%22loc%22%3A%22chr10%3A7%2C787%2C600-7%2C812%2C400%22%2C%22tracks%22%3A%5B%22muscle_plus%22%5D%7D%5D%7D&sessionName=JBrowse+docs%3A+Skeletal+muscle+RNA-seq%2C+%2B+strand+%28ENCSR609NZM%29Goes in the tracks array of config.json. See Tracks.
{
"trackId": "muscle_minus",
"name": "Skeletal muscle RNA-seq, - strand (ENCSR609NZM)",
"uri": "https://jbrowse.org/demos/dtu/ENCFF518WGP.muscle.minus.bigWig",
"assemblyNames": ["hg38"],
"displayDefaults": {
"encoding": { "y": { "scale": { "group": "coverage" } } }
}
}jbrowse add-track https://jbrowse.org/demos/dtu/ENCFF518WGP.muscle.minus.bigWig \
--trackId muscle_minus \
--name "Skeletal muscle RNA-seq, - strand (ENCSR609NZM)" \
--assemblyNames hg38 \
--displayDefaults '{"encoding":{"y":{"scale":{"group":"coverage"}}}}'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": "muscle_minus",
"name": "Skeletal muscle RNA-seq, - strand (ENCSR609NZM)",
"uri": "https://jbrowse.org/demos/dtu/ENCFF518WGP.muscle.minus.bigWig",
"assemblyNames": ["hg38"],
"displayDefaults": {
"encoding": { "y": { "scale": { "group": "coverage" } } }
}
}Open this track in JBrowse Web ↗
Needs JBrowse Desktop 5.0 or newer. If nothing opens, copy the link and paste it into Desktop's Open JBrowse Web link..., on the start screen or under File → Session.
https://jbrowse.org/code/jb2/main/?config=https%3A%2F%2Fjbrowse.org%2Fucsc%2Fhg38%2Fconfig.json&session=spec-%7B%22sessionTracks%22%3A%5B%7B%22trackId%22%3A%22muscle_minus%22%2C%22name%22%3A%22Skeletal+muscle+RNA-seq%2C+-+strand+%28ENCSR609NZM%29%22%2C%22uri%22%3A%22https%3A%2F%2Fjbrowse.org%2Fdemos%2Fdtu%2FENCFF518WGP.muscle.minus.bigWig%22%2C%22assemblyNames%22%3A%5B%22hg38%22%5D%2C%22displayDefaults%22%3A%7B%22encoding%22%3A%7B%22y%22%3A%7B%22scale%22%3A%7B%22group%22%3A%22coverage%22%7D%7D%7D%7D%7D%5D%2C%22views%22%3A%5B%7B%22type%22%3A%22LinearGenomeView%22%2C%22assembly%22%3A%22hg38%22%2C%22loc%22%3A%22chr10%3A7%2C787%2C600-7%2C812%2C400%22%2C%22tracks%22%3A%5B%22muscle_minus%22%5D%7D%5D%7D&sessionName=JBrowse+docs%3A+Skeletal+muscle+RNA-seq%2C+-+strand+%28ENCSR609NZM%29Reproduce it end to end
build_dtu_demo.sh
wraps every step above. The script:
- Downloads the ENTEx muscle and liver RSEM quantifications and GENCODE v29.
- Tests differential transcript usage with satuRn and computes each transcript's isoform-fraction change from TPM.
- Writes the statistics into the GENCODE GFF3, then bgzips and indexes it.
curl -fO https://raw.githubusercontent.com/GMOD/jbrowse-components/main/scripts/build_dtu_demo.sh
bash build_dtu_demo.sh dtu_build # writes ./dtu_build/The script needs the Prerequisites on your PATH and writes
dtu_muscle_vs_liver.gff3.gz with its .tbi index, a local build of the file
the track configuration above loads from jbrowse.org. Point the track's uri at
the local copy to open your own run.
See also
- Tutorial: RNA-seq visualization
- User guide: Gene track
- Config guide: Using jexl callbacks
External links
- Differential transcript usage in R, the same analysis written for ggjbrowse
Citations
- Gilis et al. (2021). satuRn: Scalable analysis of differential transcript usage for bulk and single-cell RNA-sequencing applications, the method behind the statistic drawn here.
- Li and Dewey (2011). RSEM: accurate transcript quantification from RNA-Seq data with or without a reference genome, the quantifier ENCODE ran.
Notes
-
The script takes the isoform fraction from TPM, because read counts scale with effective length and bias a count-based fraction toward long isoforms. It gates on satuRn's regular FDR, because the empirical FDR assumes most tests are null and this contrast breaks that assumption. ↩
Feedback on this tutorial is welcome: contact us.