Skip to content

Visualizing Sample Collections

Developer Documentation

This page is intended for users who develop tailored visualizations using the GenomeSpy app.

Getting started

You can use the following HTML template to create a web page for your visualization. The template loads the app from a content delivery network and the visualization specification from a separate spec.json file placed in the same directory. See the getting started page for more information.

<!DOCTYPE html>
<html>
  <head>
    <title>GenomeSpy</title>
    <link
      rel="stylesheet"
      type="text/css"
      href="https://cdn.jsdelivr.net/npm/@genome-spy/app@0.82.0/dist/style.css"
    />
  </head>
  <body>
    <script type="module">
      import { embed } from "https://cdn.jsdelivr.net/npm/@genome-spy/app@0.82.0/dist/index.es.js";

      await embed(document.body, "spec.json");
    </script>
  </body>
</html>

For a complete example, check the website-examples repository on GitHub.

When developing sample-collection visualizations locally, use the Inspector from the three-dot menu in the App toolbar to inspect the live view hierarchy, dataflow, params, and scale/axis/legend resolutions.

Specifying a Sample View

The GenomeSpy app extends the core library with a new view composition operator that allows visualization of multiple samples. In this context, a sample means a set of data objects representing an organism, a piece of tissue, a cell line, a single cell, etc. Each sample gets its own track in the visualization, and the behavior resembles the facet operator of Vega-Lite. However, there are subtle differences in the behavior.

A sample view is defined by the samples and spec properties. To assign a track for a data object, define a sample-identifier field using the sample channel. More complex visualizations can be created using the layer operator. Each composed view may have a different data source, enabling concurrent visualization of multiple data types. For instance, the bottom layer could display segmented copy-number data, while the top layer might show single-nucleotide variants.

{
  "samples": {
    // Optional sample identifiers and label settings
    ...
  },
  "metadata": {
    // Optional metadata sources and metadata matrix layout
    ...
  },
  "spec": {
    // A single or layer specification
    ...,
    "encoding": {
      ...,
      // The sample channel identifies the track
      "sample": {
        "field": "sampleId"
      }
    }
  }
}

But we have Band scale?

Superficially similar results can be achieved by using the "band" scale on the y channel. However, you can not adjust the intra-band y-position, as the y channel is already reserved for assigning a band for a datum. On the other hand, with the band scale, the graphical marks can span multiple bands. You could, for example, draw lines between the bands.

Implicit sample identifiers

By default, GenomeSpy extracts sample identifiers from the field encoded with the sample channel, and each sample gets its own track.

Example

This example displays four segments for each of three samples. The required samples object is empty, so GenomeSpy derives the samples and their order from the sample field in the data.

{
  "description": "A simple segmented view of three samples.",

  "data": {
    "values": [
      { "sample": "A", "start": 0, "end": 15, "state": "neutral" },
      { "sample": "A", "start": 15, "end": 20, "state": "gain" },
      { "sample": "A", "start": 20, "end": 100, "state": "neutral" },
      { "sample": "B", "start": 0, "end": 25, "state": "neutral" },
      { "sample": "B", "start": 25, "end": 55, "state": "gain" },
      { "sample": "B", "start": 55, "end": 80, "state": "loss" },
      { "sample": "B", "start": 80, "end": 100, "state": "neutral" },
      { "sample": "C", "start": 0, "end": 30, "state": "gain" },
      { "sample": "C", "start": 30, "end": 60, "state": "neutral" },
      { "sample": "C", "start": 60, "end": 85, "state": "loss" },
      { "sample": "C", "start": 85, "end": 100, "state": "gain" }
    ]
  },

  "samples": {},

  "spec": {
    "mark": "rect",
    "encoding": {
      "sample": { "field": "sample" },
      "x": { "field": "start", "type": "index" },
      "x2": { "field": "end" },
      "color": {
        "field": "state",
        "type": "nominal",
        "scale": {
          "domain": ["loss", "neutral", "gain"],
          "range": ["#5090e0", "#e0e0e0", "#ff6040"]
        }
      }
    }
  }
}

Defining sample identity

Use samples.identity when you want to define the sample order, display names, or the complete sample set independently from the visualized data.

Explicit sample identity
{
  "samples": {
    "identity": {
      "data": { "url": "samples.tsv" },
      "idField": "sample",
      "displayNameField": "displayName"
    }
  },
  ...
}

This configuration reads sample ids and display names from samples.tsv. Sample metadata, like clinical attributes, has to be provided separately in a metadata source.

The following properties configure samples.identity:

data Required
Type: UrlData | InlineData | NamedData | DynamicCallbackData | LazyData | Generator

Data source that defines the sample set for the view.

The source must contain one row per sample. Metadata imports are matched against these sample ids.

displayNameField
Type: string

Field containing a user-visible sample label.

If omitted, sample ids are used.

idField
Type: string

Field that contains the canonical sample id.

Default value: "sample"

Example

The example below defines three samples and their display names with inline identity data.

{
  "description": "Three samples with display names defined by inline identity data.",

  "samples": {
    "identity": {
      "data": {
        "values": [
          { "sample": "S1", "displayName": "Control" },
          { "sample": "S2", "displayName": "Treatment A" },
          { "sample": "S3", "displayName": "Treatment B" }
        ]
      },
      "idField": "sample",
      "displayNameField": "displayName"
    }
  },

  "spec": {
    "view": { "fill": "#f8f8f8" },
    "data": { "values": [{}] },
    "mark": { "type": "text", "text": "Data" }
  }
}

Showing sample y-axes

Sample views can show vertical axes for the repeated sample plots when the child spec defines a y-axis. By default, the axis is repeated for every visible sample whose row is tall enough. Dense views hide the axes automatically to avoid clutter.

The sample view property that enables and disables this behavior is:

sampleYAxis
Type: SampleYAxisDef | null

Controls how vertical axes are shown for repeated sample plots.

Set to null to disable sample y-axes.

Default value: {"mode": "all", "minSampleHeight": 60}

When sampleYAxis is enabled, the following properties configure how sample y-axes are shown:

mode
Type: "all" | "top" | "middle" | "bottom"

How vertical axes are shown for repeated sample plots.

- "all" shows an axis for every eligible visible sample. - "top", "middle", and "bottom" show one representative axis.

Default value: "all"

minSampleHeight
Type: number

Minimum visible sample height in pixels required before a repeated y-axis can be shown.

Default value: 60

Adjusting sample labels

The samples object controls sample labels. For example, to increase the sample label font size, use the following configuration:

Adjusting font sizes
{
  "samples": {
    ...,
    "labelFontSize": 12
  },
  ...
}

The following properties allow for fine-grained control of the font styles:

labelFont
Type: string

The font typeface. GenomeSpy uses SDF versions of Google Fonts. Check their availability at the A-Frame Fonts repository. System fonts are not supported.

Default value: "Lato"

labelFontSize
Type: number

The font size in pixels.

Default value: 11

labelFontWeight
Type: number | "thin" | "light" | "regular" | "normal" | "medium" | "bold" | "black"

The font weight. The following strings and numbers are valid values: "thin" (100), "light" (300), "regular" (400), "normal" (400), "medium" (500), "bold" (700), "black" (900)

Default value: "regular"

labelFontStyle
Type: "normal" | "italic"

The font style. Valid values: "normal" and "italic".

Default value: "normal"

labelAlign
Type: "left" | "center" | "right"

The horizontal alignment of the text. One of "left", "center", or "right".

Default value: "left"

In addition, the following sample label properties are supported:

labelTitle
Type: string | null

Title shown above sample labels. If omitted, the title defaults to "Sample". Set to null to hide the title.

labelLength
Type: number

Width reserved for sample labels in pixels.

If omitted, the width is inferred from the sample labels.

Sample row and group layout can be adjusted with the sampleLayout property:

sampleLayout
Type: SampleLayoutDef

Layout settings for sample rows and sample groups.

sampleHeight
Type: number

Height of one sample row when the view is expanded for (close-up) inspection. In the birdseye overview, sample rows are automatically scaled to fit the available vertical space.

Default value: 35

groupSpacing
Type: number

Spacing between sample groups in the fitted layout.

Default value: 5

peekGroupSpacing
Type: number

Spacing between sample groups in the expanded layout.

Default value: 15

sampleSpacingFactor
Type: number

Fraction of each sample row reserved as spacing between rendered sample contents.

Spacing is reduced when rows are too short to render cleanly.

Default value: 0.2

Metadata attribute label and matrix layout properties are documented in Configuring Metadata Sources.

For runtime parameters that respond to the sample layout and current sample set, see Sample View Parameters. For summary tracks across samples or sample groups, see Aggregating Samples.