Install
The components are published to GitHub Packages as
@biosustain/tracy-visualisations. Point the scope at
GitHub's registry, then install:
# .npmrc
@biosustain:registry=https://npm.pkg.github.com
//npm.pkg.github.com/:_authToken=${GITHUB_TOKEN}
npm install @biosustain/tracy-visualisations
The token is not optional: GitHub Packages serves npm only to
authenticated requests, public repository or not. Any token with
read:packages will do.
Importing the package registers every element; there is nothing to call. Each component is also importable on its own, so a page takes only the viewers it shows:
import '@biosustain/tracy-visualisations'; // every element below
import '@biosustain/tracy-visualisations/teal'; // <teal-trace-view>
import '@biosustain/tracy-visualisations/indigo'; // the four <indigo-*> elements
import '@biosustain/tracy-visualisations/sabre'; // <sabre-msa-view>
import '@biosustain/tracy-visualisations/pearl'; // <pearl-assembly-view>
import '@biosustain/tracy-visualisations/sage'; // the viewer teal's supersedes
// Every file is a classic script, so a page with no bundler can load one
// straight out of node_modules instead:
<script src="node_modules/@biosustain/tracy-visualisations/dist/teal.js"></script>
Splitting them is worth it: unminified, indigo's four elements are 9 kB of the default bundle's 108, and each file declares its own required globals, so a page that leaves indigo out does not need Plotly at all.
The Python CLI writes the same files, takes any selection at all, and is also how the self-contained reports linked below are built:
pip install git+https://github.com/biosustain/tracy-visualisations
# A bundle with a selection of your own
tracy-vis --emit-components gear-components.js --components teal,sage
# One self-contained report for a tracy output file
tracy-vis results.json report.html
How this page works
Every viewer below is the real element, rendering a real sample file.
This page loads exactly one script to get them —
gear-components.js, the
bundle the package installs, here emitted with sage added by name — and
then calls displayData() on each element. There is no other
JavaScript here beyond fetching the samples and wiring up the two demos
that report events back.
Each section links its sample file and the self-contained report the CLI builds from that same file: one HTML file with the components inlined, which opens from disk with no server at all.
Indigo's charts need Plotly (≥ 1.39) on the page already; every other
element is self-contained. The bundle lists what it expects in its header
banner and on window.TracyVis.requires.
<teal-trace-view>
An electropherogram drawn in SVG, from
teal. It takes a
tracy align trace, and also a raw unaligned one like the
sample here, which it normalises itself. Zoom, pan and the basecall row
are the element's own.
Markup and JavaScript
<script src="gear-components.js"></script>
<teal-trace-view id="trace"></teal-trace-view>
<script>
document.getElementById('trace').displayData(tracyJson);
</script>
<indigo-*>
Four elements from indigo, which decomposes a mixed trace into two alleles: a Plotly trace viewer, an alignment listing, the decomposition error plot, and the variants table. The chart icon on a variant row zooms the trace viewer above it to that variant — the table is handed the viewer, and drives it.
<indigo-trace-view>
<indigo-variants-view>
<indigo-alignment-view>
<indigo-decomposition-view>
Markup and JavaScript
<script src="https://cdn.plot.ly/plotly-1.39.2.min.js"></script>
<script src="gear-components.js"></script>
<indigo-trace-view id="trace"></indigo-trace-view>
<indigo-variants-view id="variants"></indigo-variants-view>
<indigo-alignment-view id="alignment"></indigo-alignment-view>
<indigo-decomposition-view id="decomposition"></indigo-decomposition-view>
<script>
var trace = document.getElementById('trace');
trace.displayData(indigoJson);
document.getElementById('decomposition').displayData(indigoJson);
// The table zooms the viewer it is given.
document.getElementById('variants').displayData(indigoJson, trace);
// The alignment view takes the two sequences already shaped, so the page
// decides what is labelled what.
document.getElementById('alignment').displayData({
alt: {
sequence: indigoJson.alt1align.replace(/-/g, ''),
alignmentString: indigoJson.alt1align,
isReverseComplement: false,
chromosome: 'Alt1',
startPosition: 1,
label: 'Alt1',
alleleFraction: indigoJson.allele1fraction
},
ref: {
sequence: indigoJson.ref1align.replace(/-/g, ''),
alignmentString: indigoJson.ref1align,
isReverseComplement: indigoJson.ref1forward === 0,
chromosome: indigoJson.ref1chr,
startPosition: indigoJson.ref1pos,
label: 'Ref'
},
charactersPerLine: 80,
score: indigoJson.align1score
});
</script>
<sabre-msa-view>
A multiple sequence alignment in wrapped blocks, from
sabre. It takes gapped
multi-FASTA — the .align.fa that tracy assemble
writes — and colours by column consensus, so where several
reads agree against the reference it is the reference base that is marked.
Hover a base: the element reports what the cursor is over as an
msa-hover event and leaves the page to place it. Changing
characters per line redraws in place, from the attribute.
Hover information
Markup and JavaScript
<script src="gear-components.js"></script>
<sabre-msa-view id="alignment" characters-per-line="80"></sabre-msa-view>
<div id="info"></div>
<script>
var alignment = document.getElementById('alignment');
alignment.addEventListener('msa-hover', function (event) {
document.getElementById('info').innerHTML = event.detail.html;
});
// Setting the property reflects to the attribute, and the element
// re-renders from attributeChangedCallback - no redraw button needed.
alignment.charactersPerLine = 100;
alignment.displayData(fastaText);
</script>
<pearl-assembly-view>
An editable assembly — several Sanger traces aligned to a reference — from
pearl. It brings its
own toolbar: the consensus overview is colour coded by agreement,
"Jump to next conflict" walks the positions that need a decision, and the
electropherograms below show every trace covering the current one. Edits
raise assembly-change, and the corrected sequence is on
userEditedSequence for the page to save.
Edit a base to see what the element reports back.
Markup and JavaScript
<script src="gear-components.js"></script>
<pearl-assembly-view id="assembly"></pearl-assembly-view>
<script>
var assembly = document.getElementById('assembly');
assembly.addEventListener('assembly-change', function (event) {
console.log(event.detail.editPosition, event.detail.userEditedSequence);
});
// Pass { prepared: true } instead to reopen a saved pearl session
// (multipleAlignment.json) with its edits intact.
assembly.displayData(pearlJson);
</script>
<sage-trace-view>
The viewer teal's supersedes, from
sage. Same class, same
entry point; teal's adds raw-trace normalisation, a responsive SVG instead
of a fixed 1200px one, and handler cleanup. It is kept registered so a
report can still be rendered with the element the earlier ones used, and
ships only when asked for by name —
--components sage. Both are on this page, which is what the
teal- and sage- prefixes are for.
Markup and JavaScript
tracy-vis --emit-components viewer.js --components teal,sage
<sage-trace-view id="trace"></sage-trace-view>
<script>
document.getElementById('trace').displayData(tracyJson);
</script>