LinearMultiSampleVariantDisplay
Auto-generated @jbrowse/mobx-state-tree API for the current JBrowse release — see pluggable elements for concepts. Provided by the variants plugin. View source.
Multi-sample variant display drawing one genotype row per sample, with a per-cell feature widget on click.
The configuration slots for this model are documented on its config schema page.
Members a composed model contributes are listed here too, so these tables are the whole surface.
Properties
| Member | Description | Defined by |
|---|---|---|
typetype: types.literal('LinearMultiSampleVariantDisplay') | LinearMultiSampleVariantDisplay | |
configurationconfiguration: ConfigurationReference(configSchema) | LinearMultiSampleVariantDisplay | |
| jexlFiltersSetting | Runtime "Filter by..." override, already jexl:-prefixed. When set (even to an empty list) it replaces the jexlFilters config slot; when undefined the config default applies. See JexlFilterModel.The name is load-bearing: this used to be called jexlFilters, the same name as the inherited config slot, so self.jexlFilters read the property and the slot was live in no reader at all — a config declaring filters on one of these tracks did nothing and said nothing. preProcessSnapshot below carries the old name over. | MultiSampleVariantBaseModel |
idid: ElementId | BaseDisplay | |
layoutlayout: types.stripDefault(types.frozen<S[]>(), []) | TreeSidebarMixin | |
| clusterTree | TreeSidebarMixin | |
| clusterProvenance | What clusterTree was computed from — the locus and the settings. Set only for a tree this app computed; a supplied phylogeny (maf's .nh) leaves it undefined. Persisted with the tree so it survives a session snapshot, which is the case that most needs it: a shared link otherwise hands over a dendrogram with no way to learn its locus. | TreeSidebarMixin |
| subtreeFilter | TreeSidebarMixin | |
runClusteringrunClustering: types.maybe(types.boolean) | Transient declarative launch spec, the same idea as LinearGenomeView's init: a session or config sets this true and the real clustering RPC runs once automatically, with no dialog, as soon as the display reports itself ready. setupRunClusteringAutorun clears it afterwards, so a saved session never re-triggers.Lives here rather than on each display because it is the trigger for a run whose output — clusterTree, clusterProvenance, layout — is this mixin's state. Three displays declared it identically, each with its own wrapper module that existed to code-split the clustering code and, along the way, hand-wrote the same six-member duck type of the display. Splitting inside the run callback does the same job and loads on a run rather than on every attach. What each run actually is stays per display, in that callback. | TreeSidebarMixin |
clusterRegionclusterRegion: types.maybe(types.string) | Where that run reads from, as a locstring (whitespace-separated for several). Clustering is region-scoped, so running it over the visible window feeds the estimator whatever happens to be on screen; naming the locus instead lets a session cluster on the signal and then show it against its context — otherwise a zoom the user has to perform in the right order. Cleared with runClustering, since it is that flag's argument and a locus left standing describes a run that is not coming. | TreeSidebarMixin |
sortRowsBysortRowsBy: types.maybe(types.frozen<RowSortSpec>()) | Transient declarative launch spec, the same idea as runClustering: set {refName, pos} to order the rows once by the value each carries at that genomic column — the session-expressible form of the right-click "Sort rows by ... here". setupRowSortAutorun applies it once the region containing it has loaded and then clears it, so the resulting layout persists but a saved session never re-sorts.Clustering orders rows by the whole region in view, and layout states an order outright. This spec ranks rows at one position, so a figure can open a cohort ranked at a candidate locus with the surrounding context still on screen. Each display defines the value at the column in its sortRows callback. | TreeSidebarMixin |
Volatiles
| Member | Description | Defined by |
|---|---|---|
hoveredCellhoveredCell: undefined as HoveredCell | undefined | The genotype cell under the pointer, as hoverInk lights it. Beside the base's hoveredFeature (the tooltip) rather than folded into it: the tooltip is the shared cross-display slot, and the box needs the cell's instance that slot has no reason to carry. | LinearMultiSampleVariantDisplay |
hoveredLaneMarkhoveredLaneMark: undefined as HitFeatureResult | undefined | The lane mark under the pointer — plugin-canvas's own hit, so hoverInk lands on the box the lane painted. | LinearMultiSampleVariantDisplay |
sourcesVolatilesourcesVolatile: undefined as Source[] | undefined | MultiSampleVariantBaseModel | |
cellDatacellData: undefined as CellDataResult | undefined | Single source of truth for fetched per-display data. sampleInfo, featuresVolatile and the summary flags are derived from this via getters — fetchNeeded only needs to call setCellData(result). | MultiSampleVariantBaseModel |
cellDataRegionIndicescellDataRegionIndices: new Set<number>() as ReadonlySet<number> | The displayed regions the current cellData was fetched for. The payload itself cannot say: a region with no variants gets no perRegionCellData entry, and the matrix payload is flat. | MultiSampleVariantBaseModel |
cellDataBpPerPxcellDataBpPerPx: undefined as number | undefined | The zoom the current cellData was fetched at, set in matrix mode alone. Matrix columns are the features of exactly the span on screen, so after a zoom inside the loaded span the held payload still lays out features the view no longer shows. Undefined answers at every zoom, as regular mode's position-drawn payload does. | MultiSampleVariantBaseModel |
errorerror: undefined as unknown | BaseDisplay | |
statusMessagestatusMessage: undefined as string | undefined | BaseDisplay | |
statusProgressstatusProgress: undefined as number | undefined | determinate progress fraction [0,1] for the current status, or undefined when the in-flight phase is indeterminate. Set alongside statusMessage by setStatusMessage; a display that never shows a bar simply leaves it undefined. | BaseDisplay |
scrollTopscrollTop: 0 | TrackHeightMixin | |
loadedRegionsloadedRegions: regionDataMap<LoadedRegion>('loadedRegions') | The per-region store, keyed by displayedRegionIndex: what a fetch asked for (the span), what it was issued under (fetchInputs) and what it brought back (payload), written as one record by ctx.commitRegion.A display's own rpcDataMap was the payload column of this map held separately, and every hook that existed to keep the two in step — clearDisplaySpecificData, a regionHasData that answered rpcDataMap.has(idx), a hand-rolled prune — was that separation's cost. A display reads the payload back through regionPayloads. | MultiRegionDisplayMixin |
forceLoadTrackforceLoadTrack: false | The force-load button's track-wide approval. Volatile so it never reaches a saved session; the forceLoad config slot is the durable form. | RegionTooLargeMixin |
byteEstimatebyteEstimate: undefined as ByteEstimate | undefined | The last byte measurement: bytes, the span they were taken at, and whether zooming has been shown not to shrink them. Survives clearAllRpcData; dropped on chromosome navigation and on a tier swap. | RegionTooLargeMixin |
gateMeasuredViewportKeygateMeasuredViewportKey: undefined as unknown | The gateViewport key the gate last asked the adapter about, on either axis — the viewport AND the settings it asked under. Separate from byteEstimate because a density refusal measures no bytes. | RegionTooLargeMixin |
canvasDrawncanvasDrawn: false | flips true on first paint; read by test selectors to detect render | RenderLifecycleMixin |
paintCountpaintCount: 0 | bumped after every frame the backend painted, so a consumer that reads this display's canvas — the circular view's ring, which copies the strip into a texture — knows when the pixels moved | RenderLifecycleMixin |
currentRenderingBackendcurrentRenderingBackend: undefined | current backend reference, updated on context-loss recovery. Typed unknown (not generic B) on purpose: this mixin is composed by every display via a non-generic factory, so the per-display backend type B isn't known here — it's supplied at attachRenderingBackend<B> and narrowed with as B inside the autoruns. Don't "fix" the cast. | RenderLifecycleMixin |
renderTickrenderTick: 0 | counter the render autorun observes; bumped to force a re-render | RenderLifecycleMixin |
autorunsInstalledautorunsInstalled: false | guards attachRenderingBackend so the autorun pair spawns once per instance | RenderLifecycleMixin |
renderErrorrenderError: undefined | the render-backend (GPU/Canvas2D init or context-loss) error, or undefined. Single source of truth for the render-error terminal state: useRenderingBackend writes it from the canvas-init mechanism so the model — not React-local hook state — owns every terminal state. Read by displayPhase (whose renderError term outranks loading, suppressing the scrim) and by DisplayChrome (shows the retry overlay). | RenderLifecycleMixin |
activeSignalactiveSignal: undefined as AbortSignal | undefined | signal of the in-flight fetch, or undefined when idle | FetchMixin |
fetchGenerationfetchGeneration: 0 | bumps at every fetch end; autoruns read it to re-evaluate, and it doubles as the staleness epoch inside runFetch | FetchMixin |
reloadCounterreloadCounter: 0 | Bumped by reload() and read unconditionally by the fetch autoruns, so a user retry re-runs the body even where nothing else moved — after an error every other fetch input is unchanged. It is also the half that survives a reload() override that forgets to invalidate, which is the dead Retry button makeRetryContractCheck reports. Declared here because this is the one mixin every fetch foundation composes, the same argument that put fetchInert below; the comparative family carried its own until ADR-105. | FetchMixin |
statusWindowstatusWindow: createStatusWindow(writeStatus(self)) | This display's status field, and the only thing that writes it: one throttle window, one slot per concurrent operation, so N parallel per-region fetches thin to one stream between them rather than N and a second operation cannot end the first one's label (ADR-081). Lent whole to createAbortRotation by a display that also runs a bare-autorun fetch — see StatusReporter. | FetchMixin |
fetchCanceledfetchCanceled: false | true after the user explicitly cancels a load (the loading overlay's cancel button → cancelFetchByUser). A durable, blocking state — unlike cancelFetch, it does not retrigger the fetch autoruns — so the load stays stopped until the user retries (reload) or the viewport changes. Any new fetch clears it (runFetch resets it at the start). | FetchMixin |
| fetchRotation | The latest-wins machine this mixin is a wrapper around, and not a second one: createAbortRotation owns abort rotation, the isCurrent guard, the status slot and the supersede-versus-end rule (ADR-080, ADR-081), for every fetch in the codebase that has one. runFetch adds the observable bookkeeping a display needs on top — isLoading, error, fetchGeneration, fetchCanceled — and nothing else.It was two implementations of that machine until 2026-08-20, which is how they came to disagree about whether a completed fetch releases its signal. A display's primary fetch is this wrapper; a second concurrent fetch on the same node holds a rotation of its own, which is why the primitive is the thing that exists and this is the thing built on it (ADR-054 §1, the one section ADR-105 keeps). It is lent this display's statusWindow, so the fetch takes a slot on the one field rather than opening a second window over it — the whole point of StatusReporter. | FetchMixin |
dismissedLegendSectionsdismissedLegendSections: [] as string[] | Ids of the scales whose section the reader closed on its own; cleared when the whole legend is shown again. Volatile where showLegend is config: which sections a reader collapsed in one sitting is not how the track is configured. | LegendMixin |
storedHoveredFeaturestoredHoveredFeature: undefined as T | undefined | StoredHoverMixin | |
hoveredTreeNodehoveredTreeNode: undefined as HoveredTreeNode | undefined | TreeSidebarMixin | |
treeCanvastreeCanvas: null as HTMLCanvasElement | null | TreeSidebarMixin | |
mouseoverCanvasmouseoverCanvas: null as HTMLCanvasElement | null | TreeSidebarMixin | |
contextMenuInfo: undefined as Info | undefined | ContextMenuMixin |
Getters
| Member | Description | Defined by |
|---|---|---|
showVariantLaneboolean | LinearMultiSampleVariantDisplay | |
variantLaneHeightnumber | LinearMultiSampleVariantDisplay | |
variantLaneLabels"auto" | "description" | "name" | "nameAndDescription" | "none" | LinearMultiSampleVariantDisplay | |
showInsertionGlyphsboolean | Whether an insertion is drawn wider than the reference span it consumes — a marker sized by the inserted bp — or at the 2px floor like a SNP. A getter and not three getConf calls, because it is the answer three separate pieces of geometry need and they must give the same one: the marker overlay, the cells' hover highlight, and their click target. All three read it through variantCellSpanPx, which is where the invariant is written down.It used to be four — the variant lane's marks were the fourth. They are plugin-canvas boxes now, and a box there is its reference span, so the band does not widen an insertion at all; the length lives in the rows' markers alone. | LinearMultiSampleVariantDisplay |
visibleRegionsVisibleRegion[] | LinearMultiSampleVariantDisplay | |
| renderState | LinearMultiSampleVariantDisplay | |
perRegionCellMapMap<number, Placed<VariantCellData>> | The one walk of perRegionCellData, and the point where a fetched cell becomes a placed cell. Every regular-mode consumer reads this map, so "does the glyph overlay see the same regions, and the same rows, as the canvas" has a single answer — the placed payload structurally satisfies VariantUploadData (GPU/Canvas upload) and VariantInsertionGlyphData (overlay), and carries featureIndexData for the hit-test index plus cellWorkerRowIndices for its lookup.This is the display's "derived region map" in the sense of ARCHITECTURE.md's re-upload-without-refetch pattern: the arrays are freshly allocated per region and never mutated in place, so a row reorder changes each entry's identity, createRegionUploadSync sees the change and re-uploads, and no RPC is involved. Rows are the only thing derived here — the worker's numbering is arbitrary and must not reach a painter.A computed returning a plain Map, for the same reason the multi-row display's is: the overlay draws inside an effect, where nothing it reads is tracked, so the read has to happen here for a refetch to repaint. Rebuilding is cheap (typical view shows 1-3 regions); MobX caches the computed so only cellData or a reorder invalidates it. | LinearMultiSampleVariantDisplay |
hoverInkHighlightRect[] | The box of the hovered genotype cell or lane mark, for the chrome's highlight. A cell is its instance through the cell mark's ink, moved down by the bands above the rows, and widened to the insertion marker where one paints over it; a lane mark is the box plugin-canvas laid out and painted, in the lane at the top. | LinearMultiSampleVariantDisplay |
highlightStyleHighlightStyle | A wash and a border: the cell colours are the data. | LinearMultiSampleVariantDisplay |
insertionGlyphRegionsMap<number, Placed<VariantCellData>> | undefined | Per-region cell data for the insertion-glyph overlay, or undefined when the slot is off. | LinearMultiSampleVariantDisplay |
drawsInsertionMarkersboolean | Overrides the base's false: this display draws the markers, so it is the one that puts them in the legend.The condition is anyMarkerPossibleForBlock, on the painter's own blocks, because the two cheaper approximations are wrong on real figures. "The window holds an insertion" puts the entry on a callset of short indels, which can never draw a marker at any zoom. "The window holds a long insertion" puts one on any view zoomed out far enough that even a long bar falls under the 2px cell floor; that was three of the fourteen committed figures carrying this display, each gaining one entry and no glyph.It asks whether a marker is drawn at ANY sub-pixel pan position, not at the one on screen. The painter's own answer flips on the snap phase — a cell of a given span measures floor(spanPx) or one more — so an exactly-painter-faithful entry blinks on and off mid-drag on the long-REF-plus-longer-ALT shape, and a single-frame export would have to settle to be right. The only divergence is an entry shown while the glyph is under the cell floor at this particular phase, which is strictly narrower than either approximation above. | LinearMultiSampleVariantDisplay |
featureIndicesMap<number, Flatbush> | Per-region spatial index over feature intervals, for the hit-test. One entry per variant, not per cell — see computeVariantCells. | LinearMultiSampleVariantDisplay |
laneDisplayConfigDisplayConfig | The plugin-canvas display config the lane's band is laid out with. See laneDisplayConfig — a literal, because a band has no config schema. | LinearMultiSampleVariantDisplay |
laneFontSizenumber | The label size the lane's marks are lettered at — plugin-canvas's, for the lane's display mode, so the width its packer reserved is the width the text draws at. | LinearMultiSampleVariantDisplay |
laneRenderDataMapReadonlyMap<number, LayoutRegionData> | The lane's marks as plugin-canvas render data, one entry per fetched region — the payload that display's own RPC produces, built here from records this display already parsed. Empty when the band is off, so every getter below it does no work. See buildLaneRenderData for why this is main-thread and costs no second fetch. A MobX computed, so it is rebuilt when the payload or the label mode changes and not per frame. Keyed off perRegionCellMap with the displayed regions' bounds, never visibleRegions: the LGV rebuilds that array fresh on every pan and zoom FRAME, so reading it here re-ran the whole chain below — SimpleFeature per record, jexl color eval, packing, label solves — ~60×/s during a drag. A region scrolled off-screen keeps its entry until its payload is cleared, which only the painter's own block clipping ever notices. | LinearMultiSampleVariantDisplay |
laneLayoutInputsOmit<LayoutInputs, "showDescriptions" | "showLabels"> | What the lane's packer reads, minus the label reservation each fit rung varies. One source, so the rungs cannot drift on zoom or orientation.coarseBpPerPx, the 500ms-debounced one, for the reason LinearBasicDisplay uses it: row packing must not recompute on every frame of a smooth zoom. Reversal off displayedRegions — stable across pan frames — for the reason laneRenderDataMap gives. | LinearMultiSampleVariantDisplay |
laneDecimatedInputsLabelRoomFactorFreeInputs | Inputs for the decimated rung, whose whitespace factor is solved against the band height. Descriptions are already gone by that rung. | LinearMultiSampleVariantDisplay |
laneFitStageFitStage | The rung the lane keeps and the scale that fills the band with it — plugin-canvas's fit ladder, run against laneHeight instead of a track height. Names and descriptions if they fit; else descriptions dropped; else names kept only where they have room; else bodies alone, squeezed and scrolled-off if even that overflows.This is the whole of "compact": the band never grows, so what adapts is how much of each record the band spends its pixels on — which is the question LinearVariantDisplay in fit mode already answers. | LinearMultiSampleVariantDisplay |
laneLaidOutDataMapReadonlyMap<number, FeatureDataResult> | What the lane's painter, its labels and its hit test all read: the resolved stack, scaled only when the fit grew or squeezed it. | LinearMultiSampleVariantDisplay |
laneContentHeightnumber | The band's own drawn height — the kept rung's stack, scaled. Less than laneHeight on a sparse window (the surplus is bottom whitespace, so a relayout packs back against the top rather than jumping to a re-centred offset) and equal to it whenever the fit had to work. | LinearMultiSampleVariantDisplay |
laneRenderedLabels{ showLabels: boolean; showDescriptions: boolean; } | Which label kinds the lane actually paints: what the kept rung reserved, so a box never reserves width for a description the band had no room to draw. | LinearMultiSampleVariantDisplay |
laneFlatbushIndexesMap<number, FlatbushRegionIndexes> | Per-region hit index over the lane's laid-out marks — plugin-canvas's, built off the same stack it painted, so the box under the cursor is the box the pick returns. Its label overhang is part of the hit box there, which is why this reads the RENDERED label flags and not the mode's. Uses Canvas's flatbushIndexes dependencies: keyed off laneLaidOutDataMap and the DEBOUNCED coarseBpPerPx, never visibleRegions (per-frame fresh) or the live block width, so the LaneHitIndexes autorun can hold it alive without per-frame rebuilds. Without that subscription its only reader is the hit test, running untracked in pointer handlers, so MobX would discard the value and rebuild a Hilbert-sorted Flatbush with a text measurement per mark on every pointer frame over the band. | LinearMultiSampleVariantDisplay |
| view | MultiSampleVariantBaseModel | |
featuresVolatileFeature[] | undefined | SimpleFeature instances derived from the simplifiedFeatures list in the most recent cellData payload. Cached by MobX while cellData is unchanged. Named featuresVolatile for backwards-compat with consumers that originally read it as a volatile field.These carry ONLY positional fields (id/start/end/refName/name) — not ALT or genotypes. Don't re-derive feature-level facts from them ( .get('ALT') etc. returns undefined); summary facts are computed in the worker and exposed as scalars (hasPhasedOrHaploid/hasSecondaryAlt/ hasUnphased), and per-feature genotype info lives in the cell-data featureGenotypeMap/featureData. | MultiSampleVariantBaseModel |
hasPhasedOrHaploidboolean | Whether any called genotype is phased or haploid, which gates the "Phased" rendering mode. Wider than the payload's hasPhased, since the painter's rule is isPhasedOrHaploid (no /), because a pangenome callset is haploid per assembly path and vg deconstruct writes bare 0/1/23 — a file with no | anywhere that phased mode renders correctly. Gating the menu on hasPhased left that rendering reachable only from the config slot. | MultiSampleVariantBaseModel |
hasSecondaryAltboolean | Whether the worker painted a secondary-alt cell (drives the "Other alt allele" legend entry). Painted, not possible: a multiallelic site nobody carries the second alt at raised this when the color was nowhere in the fetched cell data. | MultiSampleVariantBaseModel |
hasUnphasedboolean | Whether the worker painted a black unphased cell (drives the "Unphased" legend entry). | MultiSampleVariantBaseModel |
hasNoCallboolean | Whether the worker painted a no-call cell (drives the "No call" legend entry). | MultiSampleVariantBaseModel |
paintedDomainstring[] | The cell scale's domain values an alt cell was painted for in the fetched cell data — the impact tiers or SV classes the legend lists. | MultiSampleVariantBaseModel |
hasConsequenceboolean | Whether any visible variant carries a SnpEff/VEP annotation, gating the "Color by...→Consequence impact" menu option. | MultiSampleVariantBaseModel |
hasSvTypeboolean | Whether any visible variant is a structural variant, gating the "Color by...→SV type" menu option. | MultiSampleVariantBaseModel |
hasPhaseSetboolean | Whether any visible variant declares a phase set (PS in FORMAT), gating the "Color by...→Phase set" menu option. | MultiSampleVariantBaseModel |
svTypeColorsRecord<string, string> | undefined | The color assigned to each present SV type, built in the worker so the legend swatches match the painted cells (drives the "SV type" legend section). | MultiSampleVariantBaseModel |
sampleInfoRecord<string, SampleInfo> | undefined | MultiSampleVariantBaseModel | |
renderingModestring | Returns the rendering mode config slot value | MultiSampleVariantBaseModel |
lineZoneHeightnumber | Height of the connector-line zone above the rows; 0 for a display that draws variants at their genomic positions and needs no connectors. On the config rather than a bespoke property for the same reason height is (see TrackHeightMixin): a drag-resize outlives the display instance, so unticking and reticking the track keeps the zone the user set. LD declares the same slot and the same clamped setConf setter. | MultiSampleVariantBaseModel |
showRowSeparatorsboolean | MultiSampleVariantBaseModel | |
showTooltipsboolean | Whether a hover draws the tooltip table. Only the tooltip: the crosshairs, the hovered-cell highlight and hoveredFeature (the cross-display hover channel) all keep working with it off, which is the point — the reader who turns it off wants the rows uncovered, not the pointer silenced. | MultiSampleVariantBaseModel |
rowColorstring | The effective sample-grouping attribute (config default or runtime override). Drives the sidebar row coloring and the legend's group section; '' means no grouping. | MultiSampleVariantBaseModel |
facetFacetSetting | undefined | The facet object as written: the sample-metadata attribute whose values band the rows, and the band order; undefined leaves the existing order alone. | MultiSampleVariantBaseModel |
featureColorstring | Optional per-variant cell color (jexl string or CSS color) applied to alt-carrying cells; '' means default genotype coloring. Reads the raw config value directly (not getConf, which evaluates a jexl:... string immediately with no feature bound) — this crosses the RPC boundary as-is and is evaluated once per feature in the worker (see makeFeatureColor in executeVariantCellData.ts). | MultiSampleVariantBaseModel |
shadeByDosageboolean | Whether an alt cell's hue is composed with the genotype's alt dosage. A fetch input — the cells are colored in the worker. | MultiSampleVariantBaseModel |
featureWidgetType{ type: string; id: string; } | MultiSampleVariantBaseModel | |
minorAlleleFrequencyFilternumber | Returns the minor allele frequency filter config slot value | MultiSampleVariantBaseModel |
maxMissingnessFilternumber | Max fraction of no-call genotypes a variant may have before it's hidden; 1 keeps every variant | MultiSampleVariantBaseModel |
filtersSerializableFilterChain | undefined | The jexl filter expressions (from the Edit filters dialog) as a SerializableFilterChain, ready to pass as the RPC filters arg. MultiSampleVariantGet{CellData,GenotypeMatrix,ClusterGenotypeMatrix} all extend RpcMethodTypeWithFiltersAndRenameRegions, which serializes this to string[] and rebuilds it in the worker with pluginManager.jexl. | MultiSampleVariantBaseModel |
referenceDrawingModestring | MultiSampleVariantBaseModel | |
showsReferenceToggleboolean | Whether the "Show reference alleles" row belongs in this display's menu. True here: the regular display lays variants out at their genomic positions, so skip turns the gaps between them into one solid grey row and overlapping SVs read against it. The matrix packs every column with a variant and paints its reference cells in the same grey the background would be, so the toggle moves nothing there and overrides this to false. | MultiSampleVariantBaseModel |
colorByAttributesstring[] | Distinct sample-metadata attributes (from samplesTsv) the user can color rows by — every key the sources carry except internal plumbing. | MultiSampleVariantBaseModel |
domainSeededSourcesSource[] | undefined | Adapter rows in the order the config domain declares: the samples it names lead, the rest keep the file's order. The seed layout merges over — it is never written into layout, so clearLayout returns here and a domain-seeded track offers no "Reset row order" until the rows actually move. Same shape as MAF's and multi-wiggle's editableSources. | MultiSampleVariantBaseModel |
rowPaletteReadonlyMap<string, string> | undefined | The rowColor scale, attribute value -> color, held apart from the rows so a drag or a clade focus does not rebuild it over the whole cohort. undefined when there is nothing to color by. | MultiSampleVariantBaseModel |
sourcesBeforeSubtreeFilterProcessedSource[] | undefined | MultiSampleVariantBaseModel | |
sourcesBaseProcessedSource[] | undefined | MultiSampleVariantBaseModel | |
sourcesProcessedSource[] | The display rows: sourcesBase expanded for phased rendering when sampleInfo is available (sources already carrying HP, from clustering, pass through unchanged), then tinted by rowColor and banded by facet.Expansion comes first so both channels read a haplotype row's own copy of its sample's metadata — a phased clustering run writes haplotype rows into layout, and expandSourcesToHaplotypes spreads every source field onto each one.The band yields while a cluster tree describes these rows, the mechanism LinearMultiRowFeatureDisplay uses for its row groups: the dendrogram positions leaf i on row i, so banding under it would draw it against the wrong rows. A cross-band drag therefore snaps back while the facet is on and no tree is loaded, and a clustering run needs no facet write of its own.Resolved — an array, never undefined, which is the shared spelling across the row displays (canvas's multi-row painting and multi-wiggle already answered this way). sourcesVolatile and sourcesBase keep their undefined, because there it is genuinely load-bearing: sampleFilter and fetchNeeded both read sourcesBase, and its undefined → list transition is what wakes the fetch autorun (reference/FETCH_SKELETON.md §"The global-fetch trigger list must be read unconditionally"). Nothing reads this getter for that — every consumer immediately collapsed the absent case with ?.length, ?? [] or ?? 0, so the option was about eighteen defensive reads and no decision. | MultiSampleVariantBaseModel |
editableSourcesProcessedSource[] | Layout-merged, phased-expanded view for the Edit Color/Arrangement dialog. Does NOT apply the subtree filter — submitting the dialog persists every row it was shown back to layout, so a filtered list would submit the focused clade as the whole order and leave every other sample appended after it. Same reason the other row displays' editableSources sit upstream of filterRowsBySubtree.Neither the rowColor tint nor the facet band is on these rows: submit writes them straight to layout, so a channel resolved here would be persisted as if the reader had picked it row by row. | MultiSampleVariantBaseModel |
clusteringReadyboolean | Whether the fetched inputs clustering needs are present yet. Phased clustering clusters haplotypes, which needs per-sample ploidy from sampleInfo; that arrives with cellData, later than the header-only sourcesVolatile. Gating the auto-cluster run on this (not just sourcesVolatile) stops it racing ahead and building a sample-level tree whose leaves ("HG001") never match the expanded haplotype rows ("HG001 HP0"). | MultiSampleVariantBaseModel |
hasClusterableRowsboolean | Whether there is anything to cluster: clustering reorders rows, so it needs at least two rows to put in an order. An empty list is "none" and "the sample list hasn't landed yet" alike — both mean "not now", which is why one boolean answers for both and the menu's help text asks sourcesVolatile itself which of the two it is.The rows on screen, which is the list the run clusters ( sourcesBase, expanded here exactly as the worker expands it) and so the row set the tree comes back describing. Counting the unfiltered list instead offered — and let the declarative path fire — a run over a clade focused down to one row. | MultiSampleVariantBaseModel |
autoClusterReadyboolean | Whether the declarative runClustering: true path may fire: the inputs have landed AND there are rows worth ordering. Both halves are named booleans rather than one expression at the autorun, so each can be read — and tested — on its own.The dialog gates on the same pair, spelled at its own call site: the menu row that opens it carries hasClusterableRows too, but a subtree filter applied while the dialog is open can take the rows away underneath it. | MultiSampleVariantBaseModel |
sampleFilterstring[] | undefined | Which samples the worker should emit rows for, as a set — sorted and deduped, so only a membership change can move it. Row order is not a fetch input here; reference/FETCH_KEYS.md §"Row order is not a fetch input", has the why and how the three row displays each do it. Two local rules: - undefined means the sources haven't loaded, and is deliberately not reused for "all of them". fetchNeeded declines until sourcesBase exists and this key changing is the only thing that wakes it, so collapsing the two would leave it unchanged when sources landed and wedge the display with nothing drawn. - Deduped because after a phased clustering run sourcesBase is haplotype-level, listing a sample once per haplotype. The worker takes samples and expands them itself, so a key that moved with ploidy would refetch on a rendering-mode round trip that changed no sample.Reads sourcesBase, never sources, for the loop reason below. | MultiSampleVariantBaseModel |
sourceMapMap<string, ProcessedSource> | Row name -> source, for the hover tooltip. A Map for the same reason getSources' is: row names come from the file, and on a plain object a sample called constructor resolves to something inherited rather than to a miss. | MultiSampleVariantBaseModel |
genotypeSampleIndexMap<string, number> | undefined | sampleName -> column index into each feature's interned genotypeCodes. Used by the tooltips to decode a hovered cell's genotype (see genotypeCodec.ts).Rebuilt per pointer frame, not per cellData change. Its only readers are the two displays' hit tests, which run in React pointer handlers where nothing is tracked — and MobX discards an unobserved computed's value as it hands it over. So a hover walks every sample in the callset, ~60×/s, on a cohort VCF.A keep-alive autorun is the fix the canvas displays use ( CanvasHitIndexes, and see packages/display-kit/CLAUDE.md), and it does not work here yet: it evaluates this before any payload has landed, and several suites stub the cell-data RPC with a catch-all that resolves a bare [], so cellData is truthy with no sampleNames and the reaction throws. Making it holdable means giving those stubs a real payload shape first; the getter itself is fine. | MultiSampleVariantBaseModel |
rowRemapUint32Array<ArrayBufferLike> | undefined | Worker row -> screen row, the client half of taking row order out of the RPC (see sampleFilter). The cells arrive numbered against the worker's rowNames list, and rowRemap maps each to the row the user is looking at. Rebuilding it is all a reorder costs.A worker row the display isn't drawing maps to HIDDEN_ROW rather than being dropped: at that index every painter's own Y-cull puts the cell far below the canvas, so the sentinel needs no special case on either backend, in the glyph overlay, or in the SVG export. (It stays rare — the set is still a fetch input, so normally every row shipped is a row drawn.)Undefined until data lands. Consumers that draw cells must treat that as "nothing to draw yet" rather than falling back to identity: the worker's order is arbitrary, so identity would paint rows under the wrong sample names. | MultiSampleVariantBaseModel |
topBandsVariantTopBands | The bands stacked above the rows — the variant lane and the connector-line zone — resolved once. Both the layout below and the painters read this, never their own sum: see variantTopBands.ts. | MultiSampleVariantBaseModel |
rowsTopOffsetnumber | Px reserved above the rows, and so where the rows begin. This is the name TreeSidebar's model contract reads (it positions the sidebar against the rows, not against any one band), and what every component offsetting itself past the bands takes. | MultiSampleVariantBaseModel |
availableHeightnumber | Available height for rows (total height minus whatever the bands above them take). Floored at 0: lineZoneHeight (matrix only, user-draggable up to 1000 independently of height) can exceed a shrunk display height on its own, and the variant lane adds to it. Every consumer treats this as a real pixel dimension (canvas height, CSS height, scroll viewport height), so it must never go negative. | MultiSampleVariantBaseModel |
nrownumber | MultiSampleVariantBaseModel | |
autoRowHeightnumber | What fit-to-display-height divides between the rows, and the reason RowHeightMixin's non-positive floor is reachable at all here: availableHeight floors at 0, so a lineZoneHeight that swallows the whole display makes this exactly 0.A fixed height goes the other way and is used as-is however many samples there are — the rows area is a scroll viewport, so rows that don't fit cost scroll extent rather than a resize. | MultiSampleVariantBaseModel |
hierarchyClusterHierarchyNode | undefined | MultiSampleVariantBaseModel | |
rowUnmapInt32Array<ArrayBufferLike> | undefined | Screen row -> worker row, the inverse of rowRemap; -1 for a screen row this window's data has no cells for (a sample the layout draws but whose genotypes never appear in the fetched variants).The hit test needs this direction, and needs it separately, because the cell arrays stay in the worker's numbering: they are sorted by (featureIndex, rowIndex) and findCellIndex binary-searches that order, which remapping the array in place would destroy. Converting the one row the cursor is over is O(1) and keeps the search O(log n). | MultiSampleVariantBaseModel |
spatialIndexTreeSpatialIndex | undefined | MultiSampleVariantBaseModel | |
hoveredTooltipSourceVariantHoverFields | undefined | The hovered thing as the tooltip table reads it: the record's fields, with the hovered sample row's metadata attributes merged underneath them so a cohort colored by a samplesTsv column reports that column too.A hover naming no row falls through to the record's fields alone, and the variant lane's tooltip is always that case: its marks are records, so buildVariantLaneHit leaves name empty and there is no source to find here. A cell hover always finds one, because both hit tests take the name off sources, and sourceMap is built from sources.showTooltips is gated here rather than in the component, so the one getter feeding the tooltip is the one place that answers "is there a tooltip" — the hit test, hoveredFeature and the hovered-cell highlight go on reading hoveredFeature and are unaffected. | MultiSampleVariantBaseModel |
totalHeightnumber | MultiSampleVariantBaseModel | |
scrollContentHeightnumber | MultiSampleVariantBaseModel | |
scrollViewportHeightnumber | MultiSampleVariantBaseModel | |
gateEnabledboolean | Opt into RegionTooLargeMixin's byte gate: fetchNeeded passes resolvedByteLimit() to MultiSampleVariantGetCellData, whose first await on the adapter is the index estimate — so an over-budget viewport is refused before a single genotype is downloaded. | MultiSampleVariantBaseModel |
prefersOffsetboolean | Both displays fill the track with rows, so an overlapping track label would sit on top of a sample's genotypes. | MultiSampleVariantBaseModel |
colorScalesColorScale[] | LegendMixin's hook: the cell coloring, the insertion marker where one is drawn, and (when rowColor is set) the sample-grouping coloring shown on the sidebar row labels. Whether the marker is keyed is drawsInsertionMarkers' answer, the painter's own test on the painter's own blocks. | MultiSampleVariantBaseModel |
awaitingPrerequisiteboolean | Retry here is two-stage: the sources autorun reads the same reloadCounter bump reload() makes for the region fetch, and fetchNeeded below declines until sourcesBase lands. So the retry contract is judged on the run that follows, not on the declining one — see FetchMixin.awaitingPrerequisite.Strictly narrower than the declines it explains, so it defers judgement on this decline only: FetchVisibleRegions also declines when every visible block is already covered, and that one is judged as soon as sourcesBase is in hand. Not fetchNeeded's own empty-region return — the autorun only calls it with a non-empty needed, which means the view has visible regions, so that branch is unreachable from there. | MultiSampleVariantBaseModel |
parentTrackAbstractTrackModel | BaseDisplay | |
RenderingComponentFC<…> | BaseDisplay | |
| DisplayBlurb | BaseDisplay | |
adapterConfigRecord<string, unknown> | BaseDisplay | |
isMinimizedboolean | Returns true if the parent track is minimized. Used to skip expensive operations like autoruns when track is not visible. | BaseDisplay |
hoveredFeatureunknown | Overridable hook (default undefined): what the pointer is currently over, for readers outside the display. LinearGenomeViewContainer publishes it to session.hovered, the view-wide "what is the user pointing at" channel a plugin can subscribe to.Declared here because a cross-display consumer can only read a name the base declares — the same reason FetchMixin.fetchInert is a hook rather than a getter each display invents. The container used to read featureUnderMouse, which only the wiggle, alignments and Manhattan families spelled that way — canvas said hoveredFeature, variants hoveredGenotype — so the channel carried a hover from a third of the display types and nothing said which. It also asked only displays[0] of each track.unknown because the payload genuinely differs — a read, a wiggle bin, a SNP, a genotype cell — and session.hovered is typed to match ("can be anything; code that wants to deal with this should examine it"). Narrow it in the override. | BaseDisplay |
featureNounstring | Overridable hook (default 'feature'): the SINGULAR word for one of the things this display draws, as a menu row or a chip says it — "Hide this read", "Showing 3 variants".Declared here for the same reason as hoveredFeature above: it is read across the display boundary, by chrome that has no idea which display it is drawing for (SoloSelectionChip, alignments' group-label overlay), and a name only the base declares is a name every such consumer can rely on. Two displays declared it independently and one of those declarations WAS this default.A control keeps the generic word; content takes this one. "Variant height" reads as a different setting from "Feature height" when it is the same one, so the shared menus stay on "feature" however the display answers here, and the noun varies where it names what the user is looking at — "Showing 3 variants", "Hide this read". A display drawing something the generic word already fits is right to leave this alone. Distinct from the per-hit noun a context menu takes off the clicked item's own type ("mRNA", "gene"); that names one annotation, this names what the track holds. The hit noun falls back to this. | BaseDisplay |
heightnumber | TrackHeightMixin | |
resizingboolean | True for the duration of a height drag on this track, whichever handle is running it. A display whose row geometry is a function of the track height restretches every row per animation frame, and can use this to sit an expensive per-frame layer out of the drag (MAF's dense per-base letter overlay is a Canvas2D pass that scales with rows x columns). The flag itself is the track's ( BaseTrackModel), so the view brackets a drag without needing the active display to have opted into this mixin. This getter reads it so that a display that did opt in has self.resizing. | TrackHeightMixin |
scrollableHeightnumber | How far the content scrolls. A sub-pixel overflow is 0: a fit mode that divides the viewport across n rows multiplies back to a few ULPs over it, and an extent of 1e-14px still draws a scrollbar and holds the wheel away from the page. | TrackHeightMixin |
hostRegionHost | The containing LinearGenomeView, typed once for every display in this family — see containingHost for the cast it owns and why both foundations still declare the name. | MultiRegionDisplayMixin |
canvasWidthPxnumber | The CSS width of this display's on-screen canvas, in px — and the canvasWidth its renderState must carry, since the two have to agree or the bp→px mapping is scaled against a box it doesn't fill.trackWidthPx, not view.width: TrackRenderingContainer insets the rendering component by the 2px track outline under contain: strict, so a view.width-wide canvas overhangs its own container and the browser clips the overhang away. It renders almost identically, which is why MAF drifted onto view.width uncaught.A getter rather than a note on each display, because the choice was being made by copying a neighbour out of four plausible view getters — width (the viewport), this one, and totalWidthPx / totalWidthPxWithoutBorders (the content width, which the global family's heatmaps legitimately want: a different question, not a different answer). no-restricted-syntax bans the underlying read everywhere but this line, since a second spelling agrees until it doesn't.SVG export is the one exception: the export shell has no outline, so renderSvg overrides canvasWidth with the shell's own width (see LgvSvgBodyProps). | MultiRegionDisplayMixin |
settledSubPixelBinBpnumber | Genomic bp one cell of a per-base pass stands for at the settled zoom: subPixelBinBp off the host's debounced coarseBpPerPx, and 1 until the view initializes. A per-base encode or fetch reads this rather than the live zoom so a wheel tick does not redo every region. | MultiRegionDisplayMixin |
canRenderboolean | Overrides RenderLifecycleMixin's default-true hook with the LGV precondition both foundations share — see foundationCanRender. | MultiRegionDisplayMixin |
rendersCanvasboolean | Fills RenderLifecycleMixin's hook off fetchInert, as GlobalFetchMixin does: a display that will never fetch here shows a placeholder where its canvas would be. | MultiRegionDisplayMixin |
trackVisibleRegionsVisibleRegion[] | The visible blocks on the track's own assemblies, the ones this display fetches and is judged against. A view of several genomes leaves a single-genome track's other regions blank. | MultiRegionDisplayMixin |
viewportWithinLoadedDataboolean | true when every visible block lies within an already-fetched region — i.e. the viewport shows data we actually loaded, not the stale fringe left after a zoom-out/pan. Drives the loading overlay through the pre-refetch debounce. Spatial only, and it stays that way. Whether the data held for a block is still what a fetch would bring back is isCacheValid, which dataCurrent conjoins for the export gate. The scrim reads this getter and dataSuperseded, never isCacheValid: a phase that went loading on a moved fetchInputs would raise the overlay into every zoom. | MultiRegionDisplayMixin |
viewportEmptyboolean | No content block is on screen, so this display has nothing to fetch and nothing to paint — see viewportEmpty.ts for the one viewport that reaches it, how narrow that is, and why the state still has to be terminal rather than a permanent scrim. Both foundations declare it over that one expression, the same way they each declare host and paintInert. | MultiRegionDisplayMixin |
fetchSuspendedboolean | Overridable hook (default false), read by the fetch plan: the display is drawing something in the features' place and wants no fetch while it does. DensityTierMixin says it while the band is up and the gate is not blocking, so a track forced to density never downloads the features it will not draw, while a refused viewport keeps its measurement pass and the gate can still release.Not fetchInert: that one suppresses the scrim and ends the export wait, and a display saying this still has its stand-in to load. On this foundation alone, because only this family's plan reads it. | MultiRegionDisplayMixin |
layoutReadyboolean | Overridable hook (default false): whether a searchable feature layout currently exists. Any display defining a feature-lookup method (searchFeatureByID) must override it, so callers can tell "laid out, but off-display" from "no layout exists yet" — a distinction only the display can make. See packages/display-kit/CLAUDE.md §"Four readiness axes". | MultiRegionDisplayMixin |
dataSupersededboolean | Overridable hook (default false): the held data is loaded and covers the viewport, but a fetch input has moved past it, so the data is about to be refetched. A display says so here rather than overriding dataCurrent, for the reason FetchMixin.fetchInert is a hook: an override has to restate the freshness terms and then misses the next one added.Both answers a display gives about being finished read it — the export gate through dataCurrent, the loading scrim through displayPhase. The export gate is the sharper case: awaitSvgReady samples freshness once, and an export that samples it inside this window renders the data that is about to be replaced. GWAS's LD auto-index is that case: adopting the top hit as the index SNP is an rpcProps change, so the very load that produced the top hit is what it invalidates — and SettingsInvalidate lands a tick after the write, so until it does not even staleSettingsDrawn has seen it.The window is NOT invisible on screen, which this used to say while displayPhase took a spatial-only argument: alignments' per-base wall spends the debounce plus the RPC painting a 1 px stripe every 8 px, with nothing in the key having moved yet.The input need not have settled yet. Alignments counts the debounce window ahead of its per-base bin, where the bin the data was fetched under has not moved and the clear is inevitable rather than committed. That is the half of the window an export lands in, since a reader zooms and then reaches for the menu. What may NOT go in is a change that could still be taken back: this fails hung, not stale. So state the live-vs-settled half as a value compare and leave the stamp alone. The settled half — the stamp a fetch committed under against the zoomFetchArgs a fetch now would send — is the foundation's already, through the isCacheValid term in dataCurrent, and an override restating it buys nothing: a second derivation misses the field the args gain next, latches this true, and every export of the display then waits out awaitSvgReady's backstop instead of failing. | MultiRegionDisplayMixin |
renderBlocksRenderBlock[] | Shared cached view for every LGV-based GPU display. A single displayedRegion may produce multiple render blocks (shared GPU buffer, different scissor clips on screen). Plugins that want to suppress rendering in certain states (e.g. no domain yet) can override this getter to return [] — the autorun lifecycle will then issue an empty-blocks render that clears the canvas. | MultiRegionDisplayMixin |
fetchInputsFetchInputs | What a fetch issued right now would stamp on a region: the settings tier (FetchMixin.settingsFetchInputs, the tier staleSettingsDrawn compares alone) and the zoom tier (the display's zoomFetchArgs() object). fetchRegions captures it before the RPC goes out and stamps it beside the loaded region; isCacheValid compares against it. | MultiRegionDisplayMixin |
regionPayloadsReadonlyMap<number, unknown> | The store's payloads, keyed by displayedRegionIndex. A display narrows this once — get rpcDataMap() { return self.regionPayloads as ReadonlyMap<number, MyResult> } — and every reader it already had goes on reading a map.MST makes a .views() getter a computed, so the Map is built once per store change and handed back by reference after that — which is what keeps installUpload's diff a reference compare per key and a frame that changed no data free of it. While something observes it: MobX suspends an unobserved computed and rebuilds on every read, so a display whose only reader is a pointer handler needs the keep-alive canvas and Manhattan both install (display-kit/CLAUDE.md §"A hit test's index needs an observer"). The render lifecycle's upload autorun is that reader for every display that draws. | MultiRegionDisplayMixin |
hasRegionDataboolean | A fetch has landed: at least one region's payload is in the store. The render callback's first-paint gate reads this, so an empty frame before any data cannot flip canvasDrawn; an empty but loaded region counts, and paints its empty frame. | MultiRegionDisplayMixin |
staleSettingsDrawnboolean | A visible block's held data was fetched under a settings or adapter key that has since moved: drawn, and wrong for the current settings, until the refetch isCacheValid already owes lands. The loading scrim's third staleness term, beside spatial coverage and dataSuperseded — the one that used to come from SettingsInvalidate emptying the coverage map, and the reason it no longer has to.False on a zoom by construction: it compares the stamp's settings tier alone, so a moved zoom tier raises no scrim. That is the whole distance from the declined fold, which compared the whole key and put the overlay 250 ms into every zoom. | MultiRegionDisplayMixin |
dataCurrentboolean | This family's answer to the shared freshness question every display foundation must answer (dataCurrent): the held data corresponds to what is on screen right now. Four terms — spatial coverage of every visible block, loadedRegions.size to rule out the vacuously-true empty viewport, isCacheValid per block, and the display's own dataSuperseded. Regions stream in one at a time, so a multi-region/whole-genome export waits on this getter to be complete; waiting on the first datum to arrive would export a partial set.isCacheValid belongs here and not in the scrim. Coverage answers "is the data here", never "is it what a fetch now would bring back", so a zoom that moves fetchInputs leaves every held region covered and stale at once — and an export sampling svgReady across that window painted bins the worker computed for the previous zoom. displayPhase takes dataSuperseded but NOT this term: folding a moved fetchInputs into the phase raises the loading scrim into every zoom, which is the trade this does not take.The term cannot latch, and the reason is structural rather than a case list: a block reaches fetchNeeded unless planRegionFetch finds it ungated, covered AND cache-valid, and it reads that last term tracked. The && short-circuits ahead of it drop its observables only where the block is fetched anyway, so the key move that closes this gate is the same read, in the same dependency set, that wakes the refetch reopening it. | MultiRegionDisplayMixin |
| loadedAssembly | The assembly the data in hand came from, once it can answer about refNames — undefined before that.Read off the first LOADED region rather than the view's displayed ones, and defined here for that reason: a display holding fetched data is asking about the assembly THAT data is on, and the view's regions can already have moved on. The initialized gate is why this returns the assembly rather than its name. getCanonicalRefName2 and refNameToIndex answer WRONGLY rather than throwing before the aliases land — identity, and a miss — so a caller that skips the gate gets a plausible answer and no signal. Returning undefined until the aliases load forces the caller to write its fallback. | MultiRegionDisplayMixin |
phaseViewportCurrentboolean | The loading scrim's staleness argument: what is drawn answers for what is on screen. Spatial coverage, dataSuperseded and staleSettingsDrawn; NOT isCacheValid, which is dataCurrent's and would scrim every zoom. displayPhase reads it, and so does a stand-in phase (coarseTierDisplayPhase) — one predicate, so a term added here reaches both. | MultiRegionDisplayMixin |
svgReadyboolean | true once an off-screen (SVG) export can safely read this display's data. Policy single-sourced in computeSvgReady; this family supplies only the freshness half, which foundationSvgReady reads as dataCurrent or the vacuous currency of viewportEmpty. Off-screen renderers gate on it via awaitSvgReady(model) instead of inlining the condition. | MultiRegionDisplayMixin |
paintInertboolean | Fills RenderLifecycleMixin's paintInert hook — see there for why a failed fetch has to read as finished to the consumers outside the display, and foundationPaintInert for the second such state and why both fetch families answer it through one function. Overridable, as the hook is: a display with a third inert state of its own says so here. | MultiRegionDisplayMixin |
paintSupersededboolean | Fills RenderLifecycleMixin's hook with staleSettingsDrawn, so painted — and data-display-drawn through it — reads pending over a canvas painted under the previous settings until the refetch lands. clearAllRpcData used to reset canvasDrawn for the same effect; the hook says it without blanking anything. | MultiRegionDisplayMixin |
displayPhaseDisplayPhase | The display's mutually-exclusive visual state, mapped in foundationDisplayPhase — every foundation calls it and supplies only its staleness argument, so a term added to computeActivityPhase reaches all three without being wired three times.This family's argument is phaseViewportCurrent: spatial coverage AND dataSuperseded (data a settled fetch-input change is drawing wrong right now — alignments zooming perBaseLetter from 16 bp/px to 1 stays inside the loaded region and reported ready over a wall drawn as a 1 px stripe every 8 px) AND staleSettingsDrawn.A thunk, so a suppressed or already-loading display doesn't subscribe to viewport churn. A subclass customizes this through fetchInert (FetchMixin), never by overriding the getter — see that hook. | MultiRegionDisplayMixin |
byteGateAdapterConfigRecord<string, unknown> | The adapter config the gate measures — the one at byteGateAdapterPath. Overridable for a display whose adapter config is synthesized rather than read off the track. | RegionTooLargeMixin |
configuredFetchSizeLimitnumber | undefined | The display's fetchSizeLimit slot, from regionTooLargeConfigSchemaFields. number | undefined, because getConf answers undefined for a slot a composing display's schema never declared and typing it number hid the whole failure — resolveByteLimit falls back closed, and says why. | RegionTooLargeMixin |
densityTooLargeboolean | The density axis's verdict, and the whole of that axis's opt-in: CanvasFeatureGateMixin overrides it beside the measurement that fills it, and a byte-only display leaves it false. | RegionTooLargeMixin |
byteGateAdapterPathByteGateAdapterPath | Where on the track config the measured adapter sits. A tiered display overrides this one hook (MAF: ['adapter', 'summaryAdapter'] while showSummary), and both the measurement and the budget follow it. | RegionTooLargeMixin |
adapterFetchSizeLimitnumber | undefined | The measured adapter's own fetchSizeLimit slot, read off the live track config rather than the adapterConfig snapshot, which omits slots at their default. | RegionTooLargeMixin |
configForceLoadboolean | The declarative forceLoad slot. | RegionTooLargeMixin |
gateViewportGateViewport | undefined | What a measurement taken now would be about: the span on screen, and a key for the stretch of genome it covers and the settings it would be taken under. Undefined until the view is measured, and the mixin's only read of the view. Captured before the fetch's round trip, never at commit, so the stamp names the settings the worker actually counted under. The settings term is settingsFetchInputs, the axis every family invalidates data on. It belongs in the measurement because the worker's density probe counts ADMITTED features (densityGate's admit), so a filter admitting almost nothing is a different measurement of the same viewport — and while staleness was viewport-only, the main thread never went back to ask. The byte axis is an index read no rpcProps field can move; the rule is one rule rather than one per axis. | RegionTooLargeMixin |
aboveForceLoadFloorboolean | Whether the span on screen is at or above AUTO_FORCE_LOAD_BP, the one comparison against that constant. False on an unmeasured view. | RegionTooLargeMixin |
gateExemptboolean | Nothing may gate on either axis: the forceLoad slot or the button. | RegionTooLargeMixin |
estimatedFetchBytesnumber | undefined | The stored estimate's bytes; undefined when nothing has been measured. | RegionTooLargeMixin |
gateMeasurementStaleboolean | Whether the last measurement still describes what a fetch issued now would ask: the viewport on screen, under the settings on screen. True before any measurement. The triple's third term, the adapter tier, is not here — a tier swap drops the measurement outright (ClearByteEstimateOnNavOrTierSwap) rather than marking it stale. | RegionTooLargeMixin |
gateByteLimitnumber | The byte budget: the adapter's limit, else the display's, doubled below AUTO_FORCE_LOAD_BP. Read only through resolvedByteLimit(). | RegionTooLargeMixin |
gateActiveboolean | Whether the gate may act right now, on any axis: opted in, not exempt, view measured. The view is read last, so an ungated display never touches it. | RegionTooLargeMixin |
densityGateActiveboolean | Whether the density axis may act: gateActive, and the span is above the floor — the one axis the floor applies to. Whether it has anything to say is densityTooLarge. | RegionTooLargeMixin |
tooLargeStatusRegionTooLargeStatus | The verdict and its banner text, from the stored estimate against resolvedByteLimit() and the density axis when it may act. | RegionTooLargeMixin |
regionTooLargeboolean | RegionTooLargeMixin | |
regionTooLargeReasonstring | Banner text for the axis that tripped; empty when not too large. | RegionTooLargeMixin |
zoomCanReleaseGateboolean | Whether "zoom in to see features" is honest advice. Density always releases on zoom; bytes only if the last zoom-in moved the estimate. | RegionTooLargeMixin |
gateSkipsMeasuredViewportboolean | The skip both fetch skeletons apply: the banner is up and its measurement already describes the viewport on screen. | RegionTooLargeMixin |
paintedboolean | The first-paint answer every consumer outside the display should read, canvasDrawn being only the raw flag: a display that is deliberately not painting a canvas has finished, and reporting it unfinished leaves every waiter on it waiting forever.The two rendersCanvas: false states each had three of their four consumers wired by hand — the loading scrim (rendersCanvas / fetchInert) and the SVG export (fetchInert) — while the fourth, data-display-drawn, went on publishing "false" forever off the raw flag. That attribute is what PENDING_DISPLAYS (@jbrowse/browser-test-utils) selects on, so a zoomed-out reference sequence track made every waitForDisplaysDone on the page run to its full timeout, and that wait swallows its own timeout without reporting it. fetchInert on the comparative side has the same problem: the forgotten reader is the one outside the display, so the display has to publish one name for it.paintInert is the third term and the same argument once more, for the state where a display would paint a canvas and never gets to — a fetch that failed before first paint. paintSuperseded is the fourth, and the one that subtracts: a canvas painted from data a settings change has made wrong is drawn and not finished. See both hooks. | RenderLifecycleMixin |
isLoadingboolean | true while a fetch is active | FetchMixin |
isLoadingOrCanceledboolean | isLoading widened to cover a user-canceled load: what a hover gate wants, since neither state has a frame on screen that a hit describes. Not a phase input — computeActivityPhase reads the two apart, because a cancel is finished (canceled) where a fetch is not (loading). | FetchMixin |
fetchInertboolean | Overridable hook (default false): the states where this display deliberately never fetches, so it holds no data and none is coming. Sequence sets it past base resolution ("Zoom in to see sequence"); LD sets it with the triangle toggled off. One hook has three readers. A display that gains such a state declares it once, which covers the reader it would otherwise forget, always the one outside the display: - the phase ( computeActivityPhase), which otherwise parks a scrim over the placeholder, or a canceled overlay once Cancel is clicked; - the SVG export (computeSvgReady's extraTerminal), whose awaitSvgReady is an unbounded when, so one such display hangs the whole view's export; - the retry contract check (makeRetryContractCheck), which would otherwise report a dead Retry on a display correctly declining to load anything.fetchInert replaces three hooks: loadingSuppressed, svgReadyExtraTerminal on each of the two foundations, and fetchInert on the comparative family, which had already collapsed them. Both LGV displays that override it returned one expression for all three, and the global family hard-coded one of the three to false for a while, so LD could express only half its state. All three fetch families declare it here since the comparative one composed this mixin (ADR-105), so the retry check reads one field everywhere. ADR-082.A hook rather than a displayPhase override, because overriding the getter means restating the whole loading condition. Sequence held a verbatim copy of the other terms that way, and a copy misses any term added to the condition later.fetchInert lives here because this is the one mixin all three display foundations compose. Same argument, one level down, that put rendersCanvas on RenderLifecycleMixin beside canvasDrawn. | FetchMixin |
awaitingDependentDataboolean | Overridable hook (default false), read by computeActivityPhase: a load this display depends on beyond its primary fetch has not landed for the first time, so the frame the primary fetch calls current is still missing something. Multi-way synteny sets it until its lane genes and lane links first arrive, so an export or a capture never lands between the ortholog fetch and the gene models that fill the lanes.A hook rather than a displayPhase override, for the reason fetchInert is one: that display carried the override, restating the foundation's two arguments verbatim to append one term, and a copy like that misses any term added to the foundation later.Not dataSuperseded, which holds the export through every later refetch too: a display saying this wants the scrim on the first landing only, since later lane fetches redraw over lanes already on screen. | FetchMixin |
settingsFetchInputsunknown | The settings axis every fetch family invalidates on: this display's rpcProps() payload and its adapter config, as one value compared structurally. The per-region family watches it from SettingsInvalidate and stamps it on each region, the keyed families fold it into currentFetchKey, and the byte gate measures under it — one getter, so no two can come to invalidate on different axes.undefined inside the payload is a real state and a class instance compares by its own fields, which a serialized key could not say; makeSettingsFetchInputs has why. | FetchMixin |
showLegendboolean | Whether the legend is drawn. | LegendMixin |
legendTopnumber | Overridable hook (default 0): px the on-screen key is pushed down from its own inset. A display that already draws a control of its own in that corner — Hi-C's resolution box — answers that control's height; the chrome adds its own axis captions on top. The export draws no controls, so it does not read this. | LegendMixin |
legendSpecLegendSpec | The key, derived from colorScales less the sections the reader dismissed. DisplayChrome renders it on screen and renderDisplaySvg flattens it for the export, so the two describe one set of colors. | LegendMixin |
hasLegendKeyboolean | Whether the display has a key at all. The "Show legend" row is offered only when it does. Overridable for a display whose key is only waiting for data: a scale that stays empty until a region lands must not remove the toggle in the meantime. | LegendMixin |
rowHeightnumber | Raw per-row height setting: 0 is fit-to-display-height, any positive value is a fixed px height. The resolved value is effectiveRowHeight — consumers read that, never this. On the config rather than the display snapshot for the same reason height is: the config node outlives the display instance, so a fixed height survives unticking and reticking the track. | RowHeightMixin |
effectiveRowHeightnumber | Resolved per-row height. rowHeight === 0 divides the display's own autoRowHeight across the rows; any positive value is the fixed px height, used as-is however many rows there are.Sub-pixel is legitimate and deliberately not floored here — a cohort with more rows than the track has pixels has a genuinely fractional row height, and flooring it makes the content taller than the height it was asked to fit inside. resolveRowHeight floors only a non-positive result, which consumers divide by. | RowHeightMixin |
showTreeboolean | Whether the dendrogram sidebar is drawn. | TreeSidebarMixin |
showBranchLengthboolean | Whether tree nodes are positioned by branch length (dendrogram) or evenly by topology (cladogram). | TreeSidebarMixin |
showRowLabelsboolean | Whether each row's name is drawn over the left of the plot. | TreeSidebarMixin |
rowDomainstring[] | The row axis's declared order off the domain slot — the config seed orderRowsByDomain places rows through, under whatever layout says.Named for the axis rather than domain alone because the wiggle display composes WiggleCommonMixin, whose domain is the score axis's autoscaled [min, max]. Two getters of that name on one model is the later one silently answering for both. | TreeSidebarMixin |
treeAreaWidthnumber | Width in px of the sidebar the dendrogram draws in. On the config rather than the display snapshot for the same reason height is: the config node outlives the display instance, so a dragged width survives unticking and reticking the track. | TreeSidebarMixin |
parsedTreeHierarchyNode<NewickNode> | undefined | TreeSidebarMixin | |
rootHierarchyNode<NewickNode> | undefined | TreeSidebarMixin | |
treeHasBranchLengthsboolean | TreeSidebarMixin | |
rowOrderIsCustomboolean | Whether the rows have been arranged away from the order they arrived in — what "Reset row order" is offered on: a written layout. | TreeSidebarMixin |
Methods
| Member | Description | Defined by |
|---|---|---|
rpcProps() => {…} | LinearMultiSampleVariantDisplay | |
() => MenuItem[] | LinearMultiSampleVariantDisplay | |
| LinearMultiSampleVariantDisplay | ||
laneFeatureInfo(featureId: string) => VariantFeatureInfo | undefined | The record behind a lane mark, by feature id. plugin-canvas's hit test answers with an id (its payload carries no VCF fields), and the tooltip and the click both want the record — so this is the one place that crosses back, over featureGenotypeMap, the same map the genotype cells' hit test reads. | LinearMultiSampleVariantDisplay |
| laneLayoutAt | One fit candidate: the lane's stack packed with the given label reservation. plugin-canvas's packer, so overlapping SVs stack instead of overdrawing, a label is placed by the layout that reserved room for it, and paint order is the order the hit test resolves by. Non-incremental, unlike that display's four memos: those exist so a GPU upload diff stays small across a pan over a stack of hundreds of thousands of features. A band holds thousands and repaints whole. | LinearMultiSampleVariantDisplay |
| renderSvg | LinearMultiSampleVariantDisplay | |
regionHasData(displayedRegionIndex: number) => boolean | Whether the held payload was fetched for this region. A batched fetch marks only the regions it issued as loaded, but replaces the whole payload — so a region an earlier batch loaded keeps its loadedRegions entry with nothing behind it, and without this check reads as cache-valid and draws blank. In matrix mode, also whether it was fetched at the zoom on screen (cellDataBpPerPx). | MultiSampleVariantBaseModel |
configuredFilters() => string[] | What the jexlFilters config slot alone declares, jexl:-prefixed. In its own block ahead of every reader so they reach it through self, the arrangement LinearBasicDisplay uses for the same pair. | MultiSampleVariantBaseModel |
featureById(featureId: string) => Feature | undefined | The base feature a click enriches, by id — the one spelling of the lookup all three pointer surfaces (rows, lane, matrix) resolve through. | MultiSampleVariantBaseModel |
activeFilters() => string[] | The filters actually applied, jexl:-prefixed: the runtime override when set, otherwise the config tier. In its own block after configuredFilters so it reaches it through self, the arrangement LinearBasicDisplay uses for the same pair. | MultiSampleVariantBaseModel |
() => MenuItem[] | Items for the right-click menu, built from the record contextMenuInfo carries. | MultiSampleVariantBaseModel |
getPortableSettings(newDisplayId?: string | undefined) => {…} | Called by BaseTrackModel.replaceDisplay when switching between the regular and matrix variant displays. The config-slot settings (rowColor, renderingMode, etc.) now live on each display's own config-schema node rather than a display-instance override map, so porting them means writing directly into the target display's config (via setSlot) rather than spreading them into the new display's instance snapshot — hence the newDisplayId param. Only genuine display-instance state (not config-backed) is returned for the instance-snapshot spread.clusterProvenance and subtreeFilter travel with clusterTree and layout: the tree without its provenance loses the "Clustered on | MultiSampleVariantBaseModel |
| renderingProps | props passed to the renderer's React "Rendering" component. these are client-side only and never sent to the worker. includes displayModel and callbacks | BaseDisplay |
isCacheValid(displayedRegionIndex: number) => boolean | Whether the data held for a region still answers the current view. Not a hook a display fills: a display states its rule as zoomFetchArgs (what a fetch now would send the worker) and regionHasData (does what the last one stored still answer), and this compares the whole input set against the one the region was fetched under. | MultiRegionDisplayMixin |
resolvedByteLimit() => number | undefined | The budget the worker enforces and the banner compares against — the one spelling of that pair. Undefined when the gate may not act. | RegionTooLargeMixin |
gateFetchState() => GateFetchState | The gate as it stands for a fetch about to be issued. Calling it is the capture, which is why it is a method. | RegionTooLargeMixin |
svgLegendWidth() => number | Overridable hook (default 0): the width the LGV export reserves beside the plot for this legend. A display whose plot fills its band — the contact matrix, the LD triangle — answers svgLegendGutterWidth(self) so the key does not cover it. | LegendMixin |
willClearTree(next: S[]) => boolean | TreeSidebarMixin |
Actions
| Member | Description | Defined by |
|---|---|---|
setHoveredCell(cell?: HoveredCell | undefined) => void | LinearMultiSampleVariantDisplay | |
setHoveredLaneMark(mark?: HitFeatureResult | undefined) => void | LinearMultiSampleVariantDisplay | |
clearHoveredFeature() => void | The base clears the tooltip; the two highlight boxes go with it. | LinearMultiSampleVariantDisplay |
setShowVariantLane(arg: boolean) => void | Switch the variant lane on or off. The rows resize with it, because availableHeight subtracts the band, so the lane takes its space from the plot and the track keeps its height. | LinearMultiSampleVariantDisplay |
setVariantLaneHeight(arg: number) => void | Resize the variant lane, clamped. Clamped in the setter rather than at read time for the same reason setLineZoneHeight is: a drag can deliver any number, and a band dragged shut has to stay grabbable. | LinearMultiSampleVariantDisplay |
| setVariantLaneLabels | LinearMultiSampleVariantDisplay | |
startRenderingBackend(backend: VariantRenderingBackend) => void | LinearMultiSampleVariantDisplay | |
| setCellData | Store a payload and the regions it covers. One payload serves every region of a fetch and replaces the last one whole, so this is also where the previous batch's regions stop having data behind them. | MultiSampleVariantBaseModel |
setJexlFilters(f?: string[] | undefined) => void | MultiSampleVariantBaseModel | |
selectFeature(feature: Feature) => void | MultiSampleVariantBaseModel | |
setSources(sources: Source[]) => void | MultiSampleVariantBaseModel | |
setRowColor(rowColor: string) => void | Recolor sample rows by a metadata attribute (e.g. 'population'), or pass '' to clear the coloring. Records the choice in the rowColor config slot, which is the whole of it: the tint is resolved on every read of sources, so a recolor moves no rows, drops no cluster tree and writes nothing into layout. | MultiSampleVariantBaseModel |
setFacet(field: string) => void | Band the sample rows so each value of a metadata attribute (e.g. 'population') is contiguous, or pass '' to clear the facet. Writes the facet object, keeping a declared band order while the field is the one already banding, which is the whole of it: the banding is applied on every read of sources, over whatever layout holds, and it yields while a cluster tree describes those rows. | MultiSampleVariantBaseModel |
setMafFilter(arg: number) => void | MultiSampleVariantBaseModel | |
setMaxMissingnessFilter(arg: number) => void | MultiSampleVariantBaseModel | |
setPhasedMode(arg: string) => void | MultiSampleVariantBaseModel | |
setFitToHeight() => void | Enable fit-to-display-height mode: rowHeight = 0 makes effectiveRowHeight divide availableHeight across the rows. | MultiSampleVariantBaseModel |
setReferenceDrawingMode(arg: string) => void | MultiSampleVariantBaseModel | |
setShowRowSeparators(arg: boolean) => void | MultiSampleVariantBaseModel | |
setShowTooltips(arg: boolean) => void | MultiSampleVariantBaseModel | |
setFeatureColor(arg: string) => void | Set the per-variant cell color override (jexl string or CSS color), or '' to restore default genotype coloring. A fetch input — recomputes cells in the worker. | MultiSampleVariantBaseModel |
setShadeByDosage(arg: boolean) => void | Turn dosage shading on or off. A fetch input — recomputes cells in the worker. | MultiSampleVariantBaseModel |
sortByGenotype(featureId: string) => boolean | Order the rows by their genotype at one variant, breaking ties by how far each row agrees with its neighbours to either side of it. With the flanking tiebreak, rows sharing the anchor allele sit together, and their shared block frays outward at the recombination breakpoints that end it. Sorts editableSources, so the label and labelColor only layout holds move with each row and nothing has to be merged back — and so the order written back carries no rowColor tint, which those rows deliberately do not have. | MultiSampleVariantBaseModel |
sortRowsByGenotypeAt(refName: string, pos: number) => boolean | sortByGenotype at a genomic column rather than a record: the declarative sortRowsBy entry point, for a session that wants a cohort to open sorted at a locus. The variant is the loaded record covering the column; a column no record covers leaves the rows alone, the rule every "sort rows here" shares (rowSortColumn.ts).Returns whether it sorted, so sortRowsBy stays set when it did not. The shared gate only checks that a region covers the column, and this display additionally needs a record there — a session naming a variant-free column would otherwise clear its own trigger and leave the rows unsorted with nothing left to re-fire it once a record loads (setupRowSortAutorun).refName arrives canonical — the autorun normalizes it — while a record's refName is whatever the file spelled, so the comparison canonicalizes the record's side. | MultiSampleVariantBaseModel |
focusGroup(value: string) => void | Narrow the rows to one rowColor group, by the group's value — '' for the rows the attribute is blank on. | MultiSampleVariantBaseModel |
focusLegendEntry(scaleId: string, value: string) => void | The chrome's legend hook: a click on a row of the group scale focuses that group; the cell-color scales name genotypes and stay inert. | MultiSampleVariantBaseModel |
clearDisplaySpecificData() => void | MultiSampleVariantBaseModel | |
clearSettingsBakedData() => void | MultiSampleVariantBaseModel | |
fetchNeeded(_needed: IndexedRegion[]) => Promise<void> | MultiSampleVariantBaseModel | |
setStatusMessage(status?: RpcStatus | undefined) => void | BaseDisplay | |
setError(error?: unknown) => void | BaseDisplay | |
reload() => void | base display reload does nothing, see specialized displays for details | BaseDisplay |
| applyDisplaySettings | Apply a set of display settings to the live display, and report which were applied. Each key runs through the display config schema's preProcessSnapshot (shorthand expansions and legacy-key migrations, as showTrackGeneric applies to a session spec's inline track keys), then writes the matching config slot. A key naming a sub-schema (facet, color) replaces the whole object, its string shorthand lifted by that schema, and null clears it. Keys that are not slots come back in unapplied as { key, reason }, so a caller can tell a misspelling from a key that has an action instead of a slot.allowSetters also routes a non-slot key to a single-argument action named set<Key>. It is off by default because session specs, share links and embeds pass untyped JSON here, and a default fallback would let them call internal setters (setError, setScrollTop, ...) and call multi-argument setters with one argument. A caller that wants a specific action can call it directly.A key whose write threw is reported in failed. Only failed means the caller passed a bad value. unapplied needs the caller's own context to read: showTrackGeneric spreads the same settings into the display's snapshot, so a declared prop (resolution) has already landed by the time it reports here, while the restyle path spreads nothing and every entry there did nothing.A per-key error does not abort the remaining keys. A caller mid- showTrack has already pushed the track, and one rejected value should not leave it half-configured. | BaseDisplay |
setScrollTop(scrollTop: number) => void | TrackHeightMixin | |
setHeight(displayHeight: number) => number | TrackHeightMixin | |
resizeHeight(distance: number) => number | TrackHeightMixin | |
expandToContentHeight() => number | Grow the track by the content it is hiding, for the resize handle's double click. Goes through resizeHeight so grow mode's override leaves grow first. | TrackHeightMixin |
| setLoadedRegion | The raw write behind ctx.commitRegion, and not what a fetch should call. A display naming its span itself is the bug this family spent a release fixing, and the context gives a fetch no way to express it — see RegionFetchContext. Direct callers are tests staging an already-loaded display.The payload is named on every call, undefined included: this write replaces the whole record, so a re-stamp that left it off dropped the data a test had staged one line earlier, and the failure surfaced as a reader throwing three layers away. A test stages a claim with nothing behind it by saying so.An action so callers after an async boundary stay in MST strict mode. Stamps the region with the fetch key its data came back under. fetchRegions passes the key it captured before issuing the RPC; the default reads it now, which is right for a caller holding the region already and wrong for anything resuming after an await, where the viewport may have moved under the fetch. | MultiRegionDisplayMixin |
evictRegionStore(keep: ReadonlySet<number>) => void | The store's bound. Drops the entries a fetch can no longer be about: an index outside the view's buffered viewport, once the store is over MAX_STORED_REGIONS, oldest first.One rule for every display, where canvas hand-rolled pruneRpcDataMapToVisible (prune to the buffer on every fetch) and every other display had no bound at all beyond displayedRegions.length. That count is the contig count, so a fragmented assembly was effectively unbounded. The cap lets a pan back onto a recently-visited region draw immediately, which the prune-to-buffer rule did not. | MultiRegionDisplayMixin |
dropLoadedRegion(displayedRegionIndex: number) => void | Forget one region — for a display pruning what has scrolled off screen. | MultiRegionDisplayMixin |
clearAllRpcData() => void | full reset: cancels fetch, clears error, loadedRegions, display-specific data, and the canvas-drawn flag. The too-large gate is derived (a pure function of the cached estimate × viewport), so it needs no explicit clear here — the fetch autorun re-measures at the new viewport and the verdict follows. | MultiRegionDisplayMixin |
invalidateSettings() => void | SettingsInvalidate's reset: the half of clearAllRpcData a settings change still needs now that the settings and adapter axes are in fetchInputs. The in-flight fetch is superseded now rather than when its payload lands stamped stale, a blocking error or cancel is cleared so the plan is not blocked, and the display drops its settings-baked data. loadedRegions and the canvas-drawn flag stay: every held region already reads !isCacheValid, so the plan refetches it, and until that lands the data stays on screen under the scrim staleSettingsDrawn raises. | MultiRegionDisplayMixin |
| fetchRegions | Run a per-region fetch. The work callback calls ctx.commitRegion as it stores each region's payload, which is what marks it loaded — see RegionFetchContext for why this function no longer does that itself. Its only callers are the three helpers in fetchEachRegion.ts, which make that call for every display in the family; a display reaching past them owns both ctx.isStale() guards and the commit by hand, and none does.The fetch key is captured here, at issue, and carried into every commit — never re-read after the await. ctx.isStale() trips on a newer fetch or a cancel, not on a viewport that moved under a fetch that is still current, so a key read at commit time would stamp this data with a zoom it was not fetched at. | MultiRegionDisplayMixin |
afterAttach() => void | installs the fetch-lifecycle autoruns (DisplayedRegionsChange, FetchVisibleRegions, SettingsInvalidate, ClearBlockingStateOnViewportChange) | MultiRegionDisplayMixin |
clearByteEstimate() => void | Drops the estimate and the viewport stamp. forceLoadTrack survives: it is a track-wide approval. | RegionTooLargeMixin |
setForceLoadTrack(flag: boolean) => void | RegionTooLargeMixin | |
| commitFetchBytes | The byte axis of a finished fetch, called by the fetch runners with the gateFetchState() they captured at issue. Commits the per-region max; an empty batch, or an ungated display, commits nothing. | RegionTooLargeMixin |
forceLoad() => void | The banner's button: exempt the track on both axes and refetch. | RegionTooLargeMixin |
markCanvasDrawn() => void | RenderLifecycleMixin | |
resetCanvasDrawn() => void | RenderLifecycleMixin | |
stopRenderingBackend() => void | RenderLifecycleMixin | |
renderNow() => void | RenderLifecycleMixin | |
setRenderError(error: unknown) => void | set/clear the render-backend error. Called by useRenderingBackend: with the error when the canvas factory rejects (or context-loss re-init fails), and with undefined on successful (re)init and on retry. | RenderLifecycleMixin |
| attachRenderingBackend | attach a GPU/Canvas2D backend and install the upload + render autorun pair. Idempotent: re-calling swaps the backend and does not run setup again, so the callbacks and everything they close over are the first call's. | RenderLifecycleMixin |
stopActiveFetch() => void | Abort the in-flight fetch (if any) and retire its slot. The shared preamble of both cancel paths; the difference between them is only what they do to fetchCanceled / fetchGeneration afterward. | FetchMixin |
openStatusStream(isCurrent: () => boolean) => StatusStream | Open one operation's slot on the display's status field: an RPC statusCallback throttled through the display-wide window and guarded so a callback that fires after the node is torn down (RPCs resolve their status stream asynchronously) is a safe no-op, plus the clear that retires the slot when the operation ends.Every operation on the display opens one, and the two come back together because an operation that never retires keeps reporting status for a phase that is over. The viewport fetch ( runFetch), the clustering run and a lent createAbortRotation are three of them on one field; before ADR-081 each blanked the field outright and the last one to finish overwrote the status of the other two.isCurrent is required and has no "node is alive" default, because a live node is not enough: a superseded fetch is on a live node, and its late status repainting the overlay of the fetch that replaced it is the failure this guards. runFetch passes !isStale(), and every display gets that through ctx.statusCallback unasked; a caller outside a fetch (the clustering autorun) passes its own run's flag. Defaulting to isAlive made the loose answer the easy one and five displays took it.runFetch's own slot is opened by the rotation; this is for an operation outside any fetch, the tree sidebar's clustering run. | FetchMixin |
cancelFetch() => void | cancel any in-flight fetch and bump fetchGeneration (always bumps, so callers can retrigger fetch autoruns even when nothing was in flight). This is the internal reset clearAllRpcData runs — it clears any user-cancel flag so the retrigger actually re-fetches. | FetchMixin |
cancelFetchByUser() => void | User-initiated cancel from the loading overlay. Stops the in-flight fetch and lands in a durable fetchCanceled state. Unlike cancelFetch, it does NOT bump fetchGeneration — so the fetch autoruns don't immediately restart the load. The user retries via reload (the overlay's retry button), or it clears on the next viewport change. | FetchMixin |
beforeDestroy() => void | Abort an in-flight fetch on teardown. Without this, a display destroyed mid-fetch (track/view closed while loading) never signals the worker to abort the now-useless work, and its in-flight HTTP reads keep downloading. MST auto-chains lifecycle hooks, so a composing display can still define its own beforeDestroy. | FetchMixin |
beginFetch(signal: AbortSignal) => void | The onBegin half of a fetch's bookkeeping: publish the in-flight signal (isLoading) and clear the durable user-cancel — a load starting is the single clear point that covers every retrigger path (reload, viewport change, settings invalidate). An action of its own for the same reason endFetch is: installFetch's lifecycle callbacks run outside any MST flow this mixin owns. | FetchMixin |
endFetch(current: boolean) => void | The finally half of runFetch's bookkeeping, an action of its own because runFetchOnce's finally resumes on a microtask the flow does not own — a direct volatile write there is outside the action context, which is the one thing hoisting the sequence into a shared function costs. The stale branch is a superseded fetch, which must not clear the loading flag the run that replaced it just set. | FetchMixin |
runFetch(work: (ctx: FetchContext) => Promise<void>) => Promise<void> | Run a cancel-safe fetch (cancels any prior). The work callback gets a FetchContext with a signal to forward to the RPC and an isStale() check to short-circuit commits once the user has moved on. The MST-flow wrapper over the shared runFetchOnce sequence, and only the wrapper: the begin/clear/run/commit/error/end order, and the rules that keep a superseded run from writing back, are the same function every other fetch in the tree runs. What this adds is the observable bookkeeping a display needs — isLoading through activeSignal, fetchGeneration, the user-cancel clear — and the flow itself, which is an action, so work's synchronous prefix runs untracked wherever a fetch autorun calls this. | FetchMixin |
setShowLegend(arg: boolean) => void | Writes the slot, and showing the legend again restores the sections closed inside it. | LegendMixin |
dismissLegendSection(id: string) => void | Close one section of the legend, leaving the others up. | LegendMixin |
setRowHeight(n: number) => void | Pin a px row height. 0 is the fit sentinel, but enter fit mode through setFitToHeight instead — displays whose height getter is content-derived have to re-seed the slot on the way in, and that is what the action is for. | RowHeightMixin |
setHoveredFeature(hit?: T | undefined) => void | StoredHoverMixin | |
setShowTree(arg: boolean) => void | TreeSidebarMixin | |
setShowBranchLength(arg: boolean) => void | TreeSidebarMixin | |
setShowRowLabels(arg: boolean) => void | TreeSidebarMixin | |
setLayout(layout: S[]) => void | TreeSidebarMixin | |
clearLayout() => void | TreeSidebarMixin | |
setClusterTree(tree?: string | undefined) => void | TreeSidebarMixin | |
| setLayoutAndClusterTree | TreeSidebarMixin | |
setTreeAreaWidth(width: number) => void | TreeSidebarMixin | |
setSubtreeFilter(names?: string[] | undefined) => void | TreeSidebarMixin | |
setRunClustering(arg?: boolean | undefined) => void | TreeSidebarMixin | |
setClusterRegion(arg?: string | undefined) => void | TreeSidebarMixin | |
setSortRowsBy(arg?: RowSortSpec | undefined) => void | Trigger (or clear) a one-shot declarative row sort; consumed and reset by setupRowSortAutorun. A display's right-click item calls its own sort directly (instant, the data is already loaded); this is the session-level entry point. | TreeSidebarMixin |
setHoveredTreeNode(node?: HoveredTreeNode | undefined) => void | TreeSidebarMixin | |
setTreeCanvasRef(ref: HTMLCanvasElement | null) => void | TreeSidebarMixin | |
setMouseoverCanvasRef(ref: HTMLCanvasElement | null) => void | TreeSidebarMixin | |
(info: Info) => void | ContextMenuMixin | |
() => void | ContextMenuMixin |