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.

Sample: raw-trace.json — teal's own demo trace, 1451 basecalls · self-contained report

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.

Sample: indigo.json — a small fixture, as indigo publishes no demo output of its own · self-contained report · report linked to variant 0

<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.

Sample: alignment.align.fa — two reads against a reference · self-contained report

Hover information
Move the cursor over a base.
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.

Sample: assembly.json — two traces and a consensus · self-contained report, with a download button

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.

Sample: aligned-trace.json — sage's own demo trace, aligned to a reference · self-contained report (rendered with teal)

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>