Configuration

GenomeSpy exposes appearance and layout at several levels. Choosing the narrowest appropriate level keeps a specification predictable:

Level

Typical API

Scope

Mark

mark_point(size=...)

Every instance of that mark

Encoding

size="amount:Q"

Varies from row to row

View

.properties(...), .with_view(...)

One chart or composed subtree

Configuration

.configure_*()

Defaults within a configuration scope

Theme

.properties(theme=...)

Broad root-level visual preset

Explicit properties win over configured defaults. A configured point size, for example, applies only when the point mark or size encoding does not provide a more specific value. The GenomeSpy documentation describes where a default applies in config scopes and how competing defaults are settled in resolution order.

Configure one chart

This example uses all three non-data appearance levels deliberately:

import genome_spy as gs

measurements = [
    {"sample": "A", "time": 1, "value": 2.1},
    {"sample": "A", "time": 2, "value": 2.8},
    {"sample": "A", "time": 3, "value": 3.2},
    {"sample": "B", "time": 1, "value": 2.4},
    {"sample": "B", "time": 2, "value": 3.5},
    {"sample": "B", "time": 3, "value": 4.3},
]

configured_chart = (
    gs.Chart(measurements)
    .mark_point(filled=True, stroke="white", strokeWidth=1)
    .encode(
        x=gs.X("time:Q").title("Time"),
        y=gs.Y("value:Q").scale(zero=False).title("Response"),
        color=gs.Color("sample:N").legend(title="Sample"),
    )
    .properties(
        width=360,
        height=210,
        padding=gs.Paddings(top=8, right=12, bottom=4, left=12),
        title=gs.title(
            "Configured measurements",
            subtitle="Explicit properties override configured defaults",
        ),
    )
    .with_view(fill="#fafafa", stroke="#d3d3d3", strokeWidth=1)
    .configure_point(size=110, opacity=0.85)
    .configure_axis(grid=True, gridColor="#e5e5e5")
    .configure_title(anchor="start", fontSize=16, subtitleFontSize=11)
)

The responsibilities are separate:

  • mark_point() sets properties specific to these points;

  • properties() sets the title, plot size, and padding;

  • with_view() sets the current view’s background and border;

  • configure_point() supplies defaults for point marks;

  • configure_axis() and configure_title() supply guide and title defaults.

Use configure_mark() for defaults shared by every mark type and a specific method such as configure_point(), configure_rect(), or configure_text() when the default belongs to one geometry. Configuration methods merge into the chart’s config block and can be chained.

configure_view() differs from with_view(): the former supplies defaults to views in its configuration scope, while the latter explicitly styles the current view.

Titles and descriptions

A string is sufficient for a simple title:

chart.properties(title="Response by sample")

Use title() for subtitles or placement options:

chart.properties(
    title=gs.title(
        "Response by sample",
        subtitle="Six measurements",
        orient="top",
        anchor="start",
    )
)

orient chooses the side of the view and anchor positions the title along that side. Use .configure_title(...) when several titles in a composed chart should share typography. A view description is not normally drawn, but gives the chart an accessibility-oriented textual description. Reserved and overlay titles, subtitles, and styling are covered in titles.

Fixed dimensions

Numeric width and height values are plot-area sizes in logical pixels:

chart.properties(width=360, height=210)

Fixed dimensions are useful for controlled layouts and small standalone figures. Avoid hardcoding every child size in a large composition; repeated fixed values make the layout difficult to adapt.

Step sizing for discrete positions

For a nominal, ordinal, or index position, step() reserves a fixed amount of space for every scale value:

categories = [
    {"category": "A", "value": 3},
    {"category": "B", "value": 5},
    {"category": "C", "value": 2},
    {"category": "D", "value": 4},
]

step_chart = (
    gs.Chart(categories)
    .mark_rect(color="#4c78a8")
    .encode(
        x=gs.X("category:N").title("Category"),
        y=gs.Y("value:Q").title("Value"),
    )
    .properties(width=gs.step(48), title="48 pixels per category")
)

The four categories and step() produce a plot width based on four 48-pixel steps. If another category is added, the plot grows automatically. Step sizing is useful for matrices, alignments, categorical rows, and compact genome-browser tracks. See step sizing in the GenomeSpy documentation.

Container and flexible sizing

"container" allows a view to use available space. Concatenated children can combine fixed pixels with flex-like growth through SizeDef:

fixed_panel = (
    gs.Chart([{}])
    .mark_text(size=13)
    .encode(x=gs.value(0.5), y=gs.value(0.5), text=gs.value("Fixed: 120 px"))
    .properties(width=120, height=80)
    .with_view(fill="#eef3f8", stroke="#9eb4c8")
)
growing_panel = (
    gs.Chart([{}])
    .mark_text(size=13)
    .encode(x=gs.value(0.5), y=gs.value(0.5), text=gs.value("Flexible: grow=1"))
    .properties(width=gs.SizeDef(grow=1, minPx=180), height=80)
    .with_view(fill="#f8f1ea", stroke="#cfaa83")
)

flex_chart = (fixed_panel | growing_panel).properties(
    width="container", spacing=8, title="Fixed and flexible child widths"
)

The left child has a fixed 120-pixel plot width. The right child has grow=1, so it receives remaining horizontal space, while minPx=180 prevents it from becoming too narrow. SizeDef can combine:

  • px for an absolute component;

  • grow for a share of remaining space;

  • minPx and maxPx for constraints.

Use viewportWidth or viewportHeight when the content should retain its calculated size but appear inside a smaller scrollable viewport. This is often preferable to squeezing a long categorical or sequence view. The scrollable viewport example shows this on a long view. The GenomeSpy documentation covers both in child sizing and scrollable viewports.

Padding and spacing

padding reserves space around one view. Use a number for equal padding or Paddings for individual edges:

chart.properties(
    padding=gs.Paddings(top=8, right=12, bottom=4, left=12)
)

spacing is different: it controls the gaps between children of a concatenation. Keep padding local to the view that needs breathing room and spacing on the parent that arranges the children.

Built-in themes

A theme supplies a coordinated set of broad defaults. Theme selection belongs on the root specification:

themed_chart = (
    gs.Chart(measurements)
    .mark_point(filled=True, size=100)
    .encode(x="time:Q", y="value:Q", color="sample:N")
    .properties(
        width="container",
        height="container",
        title="The Quartz built-in theme",
        theme="quartz",
    )
)

Available built-in themes include genomespy, vegalite, quartz, dark, fivethirtyeight, and urbaninstitute. The default is genomespy. The current list and a preview of each theme are in built-in themes.

Use a theme for the broad visual language, configuration for repeated defaults, and explicit properties for intentional exceptions. Local explicit properties take precedence over both configuration and theme defaults.