Create and update charts in notebooks¶
GenomeSpy charts display through a notebook widget in JupyterLab, Jupyter Notebook, VS Code notebooks, and Marimo. The browser needs network access when it first loads the pinned GenomeSpy JavaScript bundle.
Install for notebooks¶
Install the package with Arrow support when using it in a notebook. This also installs PyArrow for dataframe transport:
pip install "genome-spy-python[arrow]"
Display a chart¶
Build a chart normally:
initial_rows = [
{"sample": "A", "value": 2.1, "group": "control"},
{"sample": "B", "value": 3.4, "group": "control"},
{"sample": "C", "value": 4.2, "group": "treated"},
]
chart = (
gs.Chart(
data={"name": "measurements"},
datasets={"measurements": initial_rows},
)
.mark_point(filled=True, size=120)
.encode(
x=gs.X("sample:N").title("Sample"),
y=gs.Y("value:Q").title("Measurement"),
color=gs.Color("group:N"),
)
.properties(height=180, title="Notebook measurements")
)
Leave the chart as the final expression in a notebook cell to display it:
# Leave the chart as the final expression in a notebook cell.
chart
This form is enough when later Python cells do not need to update the displayed data.
Display a dataframe¶
Chart accepts pandas and Polars dataframes, plus PyArrow Table and
RecordBatch objects:
import genome_spy as gs
import pandas as pd
frame = pd.DataFrame({"sample": ["A", "B"], "value": [2.1, 3.4]})
chart = gs.Chart(frame).mark_point().encode(x="sample:N", y="value:Q")
chart
Notebook rendering transfers supported tables with Arrow automatically. This
changes only how data reaches the widget: to_dict() and
to_json() still produce ordinary JSON-compatible specifications. A
pandas index is not a chart field, so use frame.reset_index() first when the
index contains values the chart needs.
Keep a widget for updates¶
Call widget() when the displayed chart must receive new data:
view = chart.widget()
# Display this object once in the notebook.
view
Display view once and keep the same object alive. Updating it preserves the
mounted GenomeSpy instance, including its current zoom and selections.
The chart uses a named dataset:
data={"name": "measurements"},
datasets={"measurements": initial_rows},
data.name tells the chart which dataset to read. The root datasets mapping
provides its initial rows and gives later updates a stable target. The GenomeSpy
documentation describes this indirection in
named data.
Equal unnamed tables are shared automatically. Updating a shared dataset changes all charts that read it. Use different explicit names when charts need independent updates, even if they start with the same rows. See Reuse a table across charts.
Replace the named dataset¶
Use set_dataset() to replace its records:
updated_rows = [
{"sample": "A", "value": 2.8, "group": "control"},
{"sample": "B", "value": 3.1, "group": "control"},
{"sample": "C", "value": 4.7, "group": "treated"},
]
view.set_dataset("measurements", updated_rows, format="records")
New rows should retain the fields and value types expected by the chart. For a
widget with exactly one named dataset, view.set_data(updated_rows, format="records") is a shorter equivalent.
Dataframes and PyArrow tables can be passed directly:
view.set_dataset("measurements", updated_frame)
Arrow is the default transport for these updates. Keep column names and value
types compatible with the chart fields. Most users do not need to call
to_arrow_ipc() directly.
In a reactive notebook, create and display the widget in a stable cell. Let
dependent cells prepare new rows and call set_dataset() on that same object.
Create a new chart only when its fields, marks, encodings, or composition need
to change.
Use Marimo¶
Marimo displays the same widget through its anywidget support. Create and wrap the widget once in a stable cell:
import marimo as mo
view = chart.widget()
chart_widget = mo.ui.anywidget(view)
chart_widget
Dependent cells can prepare a new dataframe and update the existing widget:
view.set_dataset("measurements", updated_frame)
Keeping the widget in its original cell avoids rebuilding the chart whenever a Marimo control changes.
See the genome_spy.api.JupyterChart reference for multiple datasets,
transport options, and method signatures.
If a chart does not appear¶
Make sure the package is installed in the Python environment your notebook
uses. After installing or upgrading it, restart the notebook’s Python session
and rerun the cells. The chart also needs internet access to load its display
code. As an alternative, use save() to save an
HTML file and open it in a browser.