Runtime State¶
Named data¶
Named data sources allow data to be provided at runtime instead of loading it
from a URL. Declare every named dataset in the datasets property of the view
that owns it, and reference it with data.name:
{
"datasets": {
"myResults": []
},
"data": {
"name": "myResults"
},
...
}
datasets declarations are lexically scoped through nested views. A view can
reference a dataset declared on itself or an enclosing view. A more deeply
nested declaration with the same name shadows the enclosing declaration.
Repeated import instances therefore own independent datasets. The declaration
establishes the owner used for scoped runtime updates.
Updating named data¶
Use the embed-level datasets API for a dataset declared by the top-level input
specification:
const api = await embed("#container", spec);
api.datasets.set("myResults", [
{ x: 1, y: 2 },
{ x: 2, y: 3 },
]);
api.datasets always targets the top-level authored specification, even when
GenomeSpy adds an implicit layout wrapper. It never searches nested views by
name.
For a declaration in a nested or imported view, use the exact declaring view's
datasets API:
const owner = api.views.get({
scope: ["translationA"],
view: "translationA",
});
owner.datasets.set("geneticCode", rows);
Updates do not search ancestors or descendants. Exact ownership keeps updates unambiguous when multiple subtrees use the same dataset name.
datasets.reset() removes the runtime override and restores the values from
the declaration:
api.datasets.reset("myResults");
To avoid an initially empty dataset, a host can place initial rows in the JavaScript specification before embedding:
spec.datasets.myResults = initialRows;
const api = await embed("#container", spec);
Named data can be updated dynamically, but it does not automatically react to user interactions. For practical examples, see the embed-examples package.
Deprecated global APIs¶
api.updateNamedData(name, data) and the namedDataProvider embed option are
deprecated. They use embed-wide name lookup, which cannot address repeated or
shadowed declarations reliably.
Existing integrations may continue using them during the compatibility period.
A global update throws when the name identifies multiple scoped datasets.
Migrate by adding a datasets declaration to the intended owner and calling
api.datasets.set() or api.datasets.reset() for a top-level declaration, or
the owning view handle's datasets methods for a nested declaration.
Undeclared data.name references also retain their embed-wide fallback
behavior temporarily. New specifications should declare every named dataset
explicitly.
Named scales¶
A scale resolution is the scale instance shared by one or more view encodings. Composition settings determine whether child views share a scale resolution or use independent ones. See Scale, Axis, and Legend Resolution.
Name a scale resolution with scale.name to access it from the embed API with
getScaleResolutionByName(name). The name identifies the resolved scale, not an
individual view encoding. Shared encodings can use the same scale.name, while
independent scale resolutions must have unique names.
getScaleResolutionByName(name) returns undefined when the name is not
registered.
Named scales are useful when host application code needs to read the current domain, zoom a view programmatically, or synchronize domains between embedded GenomeSpy instances. See also Scale.
{
"encoding": {
"x": {
"field": "x",
"type": "quantitative",
"scale": {
"name": "detailScale",
"domain": [0, 100],
"zoom": true
}
}
}
}
const detailScale = api.getScaleResolutionByName("detailScale");
if (!detailScale) {
throw new Error("Missing named scale: detailScale");
}
console.log(detailScale.getDomain());
await detailScale.zoomTo([25, 50]);
Domains¶
getDomain() returns the current domain used by the scale. For locus scales,
this is the linearized numeric domain.
getComplexDomain() returns the current domain converted back to complex
domain values when available, such as genomic loci for locus scales. See
Specifying the domain for locus
domain syntax.
const genomeScale = api.getScaleResolutionByName("genomeScale");
if (!genomeScale) {
throw new Error("Missing named scale: genomeScale");
}
console.log(genomeScale.getDomain());
console.log(genomeScale.getComplexDomain());
For a locus scale, zoomTo() accepts either a linearized numeric interval or a
complex genomic interval:
await genomeScale.zoomTo([{ chrom: "chr8" }, { chrom: "chr10" }]);
await genomeScale.zoomTo([400_000_000, 500_000_000]);
Pass { duration: true } or { duration: milliseconds } to animate the zoom:
await genomeScale.zoomTo([{ chrom: "chr1" }, { chrom: "chrM" }], {
duration: true,
});
Domain events¶
Named scales emit a "domain" event when their domain changes. Listen to the
event when external UI must reflect zoom or pan state:
const genomeScale = api.getScaleResolutionByName("genomeScale");
if (!genomeScale) {
throw new Error("Missing named scale: genomeScale");
}
const listener = (event) => {
console.log(event.scaleResolution.getComplexDomain());
};
genomeScale.addEventListener("domain", listener);
Remove listeners when they are no longer needed:
genomeScale.removeEventListener("domain", listener);
Domain events can also drive application-level linking. For example, a brush
parameter in one embed can call zoomTo() on a named scale in another embed.
For examples, see the scaleApi, brushLinkingApi, and linkedEmbeds pages
in the
embed-examples
package.
Parameters¶
Named parameters can be accessed through getParam(). The returned handle can
read and write the parameter value and subscribe to changes:
const api = await embed(container, spec);
const threshold = api.getParam("threshold");
console.log(threshold.getValue());
threshold.setValue(5);
const unsubscribe = threshold.subscribe((value) => {
console.log("threshold changed", value);
});
Variable parameters and interval selections can be read and written.
intervalSelection() constructs interval selection values:
import { embed, intervalSelection } from "@genome-spy/core";
const brush = api.getParam("brush");
brush.setValue(intervalSelection({ x: [10, 20] }));
Current limitations:
- Parameters are addressed by name only. If the name resolves to multiple
independent parameters,
getParam()throws an ambiguity error. - Parameters declared with
push: "outer"are resolved as aliases of the outer parameter they write to. - Computed
exprparameters are readable but cannot be written. - Point selections are readable but cannot be written through the API because valid values require GenomeSpy-generated datum ids.
- Projected selections are not supported.
For spec-side parameter behavior, including input bindings, selections, and
push: "outer" for linking scale domains, see
Parameters.
For examples, see the paramApi and brushLinkingApi pages in the
embed-examples
package.