SharedLDModel
Auto-generated @jbrowse/mobx-state-tree API for the current JBrowse release — see pluggable elements for concepts. Provided by the variants plugin. View source.
Shared state model for LD displays
Members a composed model contributes are listed here too, so these tables are the whole surface.
Properties
| Member | Description | Defined by |
|---|---|---|
configurationconfiguration: ConfigurationReference(configSchema) | SharedLDModel | |
idid: ElementId | BaseDisplay | |
typetype: types.string | BaseDisplay |
Volatiles
| Member | Description | Defined by |
|---|---|---|
rpcDatarpcData: null as LDDataResult | null | SharedLDModel | |
focalSnpLocusfocalSnpLocus: undefined as string | undefined | Locus (refName:start) of the focal SNP whose LD row+column is emphasized, or undefined. Keyed by locus rather than array index so the selection survives a re-fetch that reorders SNPs. | SharedLDModel |
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 | |
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 |
loadedFetchKeyloadedFetchKey: undefined as FetchKey | undefined | currentFetchKey as it stood when the held data was committed — the loaded half of the freshness compare. Written only by commitFetchResult, so a display cannot stamp data it did not fetch, and cleared by reload for the overlay's sake rather than the refetch's (the skeleton's reload epoch is what overrides its gate). The data itself stays display-owned: arc keeps stale arcs on screen under the loading overlay, HiC the stale matrix, synteny the stale ribbons. | KeyedFetchMixin |
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 |
Getters
| Member | Description | Defined by |
|---|---|---|
| view | SharedLDModel | |
prefersOffsetboolean | SharedLDModel | |
lineZoneHeightnumber | SharedLDModel | |
ldMetric"dprime" | "r2" | SharedLDModel | |
showLDTriangleboolean | SharedLDModel | |
squashToHeightboolean | SharedLDModel | |
maxVariantSeparationnumber | SharedLDModel | |
showVerticalGuidesboolean | SharedLDModel | |
showLabelsboolean | SharedLDModel | |
tickHeightnumber | SharedLDModel | |
useGenomicPositionsboolean | SharedLDModel | |
snpsLDSnp[] | The loaded matrix's SNPs, in the order they are drawn along the column axis (the worker puts them in screen order — see RenderLDDataRPC/reversedRegions.ts). Empty until data arrives. | SharedLDModel |
cellWidthnumber | Fetch-time width of one column in the un-rotated frame (uniformW). Read through columnX, which rescales it to the live viewport. | SharedLDModel |
viewSignaturestring | undefined | LD's half of GlobalFetchMixin's freshness compare: the dynamic-block set. LD's SNP set is viewport-defined (the index-mode triangle spans the visible blocks), so a pan refetches — but worker output is genomic, so the stale triangle draws at its own position under the live transform while the refetch runs. The settings axis — what keeps svgReady from capturing a matrix computed under the filters the user just changed — rides in through the settingsFetchInputs half the mixin pairs it with. | SharedLDModel |
fetchInertboolean | With the triangle off the display shows an EmptyState ("Enable LD triangle…") instead of a canvas and its prepare declines forever, so nothing is loading and nothing ever will. Every reader needs that: the scrim would otherwise park over the placeholder — permanently, once a cancel has been clicked, since fetchCanceled is durable — awaitSvgReady is an unbounded when, so one such track hangs the whole view's SVG export, and canvasDrawn never flips, so painted reads off this through the foundation's rendersCanvas. | SharedLDModel |
effectiveLdMetricLDMetric | Metric the loaded data actually represents. A pre-computed file with no D' column downgrades a 'dprime' request to 'r2', so the legend and the metric radios read this rather than the raw requested ldMetric. | SharedLDModel |
colorScalesColorScale[] | LegendMixin's hook: the metric's ramp, read out of the same 256-entry LUT the cells are painted through (and the GPU samples as its ramp texture), one stop per source-table knot. Derived rather than restated, so the key cannot stop describing the plot beside it. | SharedLDModel |
effectiveUseGenomicPositionsboolean | Whether the loaded matrix was actually laid out at genomic positions. The worker falls back to uniform cells when the viewport holds more than one region (SNPs from the later ones would collapse onto the first's coordinates), so the raw slot can say yes while what is on screen is index-laid-out. Every consumer that branches on the layout — the hit test, the zone height, the connectors-vs-labels choice — reads this, not the slot, or it describes a matrix that isn't there. Same requested-vs-loaded split as effectiveLdMetric; rpcProps still sends the slot, which is the request. | SharedLDModel |
r2Availableboolean | Whether the file carries an R2 column. A --r2 dprime emit does not, and the r² radio is disabled against it rather than serving D' under the wrong name. | SharedLDModel |
dprimeAvailableboolean | Whether the D' metric can be shown — false only for a pre-computed file lacking a DP column, which disables the D' option. | SharedLDModel |
loadedLDWindownumber | undefined | The pair-separation window the LOADED matrix was computed at, in variants, or undefined when it covers the whole triangle. Read off the result rather than off maxVariantSeparation: the slot is a request, and resolveBand clamps it to n - 1, at which point there is no window to report.The status bar names it because nothing else on screen can. A pair past the window is not drawn, and an in-band pair at r² = 0 is painted at the ramp's white end at full alpha — so against a light theme's background "not measured" and "no linkage" are the same pixel, and long-range LD, which is the interesting case, reads as absent rather than as unasked. | SharedLDModel |
focalSnpIndexnumber | Array index of the focal SNP in the current snps, or -1 if none is selected or the locus is no longer present after a re-fetch. | SharedLDModel |
gateEnabledboolean | Off: RegionTooLargeMixin's gate is a byte axis, and the byte estimate comes from a feature adapter's index. An LD record source serves no features, so there is nothing to measure and the gate can only ever return "unmeasurable". Turning the gate off keeps the banner and the force-load control off a display where neither can act. | SharedLDModel |
effectiveLineZoneHeightnumber | Pixel height of the SVG zone above the canvas (variant labels + lines). The hit-test subtracts this from mouseY before reversing the render transform. | SharedLDModel |
ldCanvasHeightnumber | Effective height for the LD canvas (total height minus the zone the variant lines occupy above the matrix). | SharedLDModel |
canvasWidthnumber | The box the triangle is drawn in. One pair for all three of the canvas element's CSS size, the backing store the rendering backends resize to, and the SVG export's paint layer — they have to be the same number or the drawn matrix is stretched against the box it sits in, and they were previously derived independently on either side of that boundary.totalWidthPx here and totalWidthPxWithoutBorders for the triangle's base, as the Hi-C display splits them: scrolled left of the genome start the triangle is drawn from the left gap onward, so a box only as wide as its base cut the gap's width off its right corner. | SharedLDModel |
canvasHeightnumber | Height of that box: the triangle's natural apex height (half its width), or the display's own height when squashed to fit. | SharedLDModel |
yScalarnumber | Per-frame yScalar squash factor. When squashToHeight is on, squashes the natural (base/2) triangle into ldCanvasHeight. Lives on the main thread so resize doesn't trigger a worker re-fetch. | SharedLDModel |
renderStateLDRenderState | Per-frame render state for the GPU backend. Read by the upload/render autorun — every change to any tracked observable (view.bpPerPx, view.offsetPx, model.squashToHeight, rpcData contents, …) re-fires it. | SharedLDModel |
ldRegionsReadonlyMap<number, LDUploadData> | The matrix as the mark backend's region map: one payload under key 0, left out until the fetch lands so the backend answers "nothing drawn" and the loading scrim stays over a blank canvas. A matrix that computed zero cells keeps the key — the cleared canvas IS the picture for a window with no pairs, and nothing later will upload bytes for it. The narrowing the SVG export reads too, so the export cannot pack the matrix differently from the screen. | SharedLDModel |
ldBlocksRenderBlock[] | The one block the mark backend draws: the whole canvas. | SharedLDModel |
viewTransform{ viewScale: number; viewOffsetX: number; } | The per-frame map from the payload's pre-rotation data space to canvas px; triangleViewTransform owns the arithmetic and says why. | SharedLDModel |
connectorLineCoordsConnectorCoord[] | The connector lines tying each matrix column to its SNP's genomic position, in viewport pixels, plus the label the hover tooltip and VariantLabels show. Only meaningful in index mode (genomic-positions mode already draws columns at their genomic x). | SharedLDModel |
| triangleTransform | The whole triangle map as the shared TriangleTransform: the view scale/offset, the fit-to-height squash, and the connector zone LD reserves above the matrix. One value, so cellToScreen and screenToCell below cannot disagree about a term — a dropped yScalar in a hand-spelled inverse survived the coarse round-trip test here once. | SharedLDModel |
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 |
featureWidgetType{ type: string; id: string; } | The widget openFeatureWidget opens for one of this display's features. Displays may override it. The default is the generic feature widget, for displays drawing plain features.Displays whose features are a specific kind (a read, a variant, a synteny block) override it, including the id: two displays naming one id share the drawer panel, which suits two displays showing the same kind of feature. | 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 |
scrollContentHeightnumber | Overridable hook: the height of the content that scrolls, in px. | TrackHeightMixin |
scrollViewportHeightnumber | Overridable hook: the height of the window it scrolls behind, in px. | 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 hosting view as the RegionHost contract — see containingHost for the cast it owns, why the name is host and not view, and why both foundations still declare the name over one body. | GlobalFetchMixin |
staticBlockSignaturestring | undefined | The static-block set as a signature, or undefined before the view is measured — the building block every viewSignature in this family starts from. Arc and multi-way synteny are exactly this; HiC appends its resolution. Declared here so the initialized gate is spelled once. | GlobalFetchMixin |
dynamicBlockSignaturestring | undefined | The same over dynamicBlocks, for a display whose fetch window is the live viewport rather than the snapped block set (LD). | GlobalFetchMixin |
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. | GlobalFetchMixin |
canRenderboolean | Overrides RenderLifecycleMixin's default-true hook with the LGV precondition both foundations share — see foundationCanRender. | GlobalFetchMixin |
rendersCanvasboolean | Fills RenderLifecycleMixin's hook off fetchInert: a display that will never fetch here shows a placeholder where its canvas would be, so painted and the pre-first-paint scrim term stop waiting on a paint that cannot come. Sequence and LD each carried this as a second override beside fetchInert, always its negation. | GlobalFetchMixin |
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. | GlobalFetchMixin |
svgReadyboolean | Policy single-sourced in computeSvgReady; this family supplies only the freshness half, which foundationSvgReady reads as dataCurrent or the vacuous currency of viewportEmpty. Note it requires the dataset to actually be current, NOT merely "not currently fetching": the fetch trigger is a debounced afterAttach autorun, so at export time isLoading can still be false with no data yet — a displayPhase !== 'loading' test would then capture an empty render. Never gates on canvasDrawn, which an off-screen export never sets. Off-screen renderers gate on it via awaitSvgReady(model). | GlobalFetchMixin |
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 of them without being wired twice.This family's argument is the constant true, deliberately: a global display keeps the last frame up through a refetch (worker output is genomic, so the stale frame draws correctly under the live view transform), so a pan or zoom shows no scrim beyond the isLoading window. The pre-first-paint scrim it does want — the gap between mount and isLoading going true, which on HiC is the CoreGetInfo round trip its first fetch waits on — is computeActivityPhase's shared rendersCanvas && !canvasDrawn term, not anything this family spells out.A display with no rendering backend narrows this to the backend-free DisplayStatusPhase with foundationDisplayStatusPhase, as arc does. Arc cannot reach renderError, and the narrower type lets DisplayStatusChrome take it with neither a cast nor a dead branch. | GlobalFetchMixin |
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 |
paintSupersededboolean | Overridable hook (default false): what is on the canvas was painted from data a later change has made wrong, so painted below should answer pending until the repaint lands even though canvasDrawn is still true. The per-region fetch foundation fills it with staleSettingsDrawn — held data drawn under settings that have since moved — which is the state clearAllRpcData used to express by resetting canvasDrawn on every settings change, blanking the display to do it. A capture waiting on data-display-drawn then waits for the refetch rather than snapshotting the previous setting's pixels.A hook and not a reset of the flag, because the flag is re-marked by any redraw — a pan between the settings change and the refetch would report the stale canvas drawn — and a derivation cannot be raced. | RenderLifecycleMixin |
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 |
dataSupersededboolean | Overridable hook (default false): the held data answers the key, but this display knows it is not what the screen will settle on — a dependent fetch of its own is still out, or a fetch input it writes itself has moved. The same hook MultiRegionDisplayMixin declares, for the same reason: the key compare is structurally blind to anything the display fetches outside its primary fetch, and an export sampling svgReady in that window paints the half-filled frame.A term of dataCurrent and NOT of the skeleton's freshness gate, so it holds the export and never re-runs the primary fetch. It fails hung, not stale: a value that latches true parks awaitSvgReady on its backstop, so state only what a later commit is guaranteed to clear. | KeyedFetchMixin |
currentFetchKeyFetchKey | undefined | Key of the fetch the current view, settings and adapter call for. The fetch skeleton's freshness key: captured at issue, compared against the stamp above, and written to it at commit. Its identity survives a recomputation onto equal content, so the idle compare is ===. | KeyedFetchMixin |
dataCurrentboolean | The shared freshness answer every foundation gives: data has been committed (loadedFetchKey is only ever written beside it), it was fetched for the current view and settings, and the display is not about to supersede it itself. A pan inside the loaded blocks stays current; a block entering, a tier step, a settings change or a reload() moves one side of the compare. What the fetch autorun gates on is the same compare inside installFetch, not this getter — the skeleton owns it so a reload can override it. This one is for the readers outside the fetch, the export gate above all. The per-region twin is isCacheValid: what decides a refetch, and deliberately not the whole freshness answer. | KeyedFetchMixin |
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 |
awaitingPrerequisiteboolean | Overridable hook (default false), read only by the retry contract check (makeRetryContractCheck): "this run declined because a prerequisite fetch in another autorun has not landed, and its arrival wakes this one again". It defers the retry verdict to that later run rather than waiving it, so a display cannot spend its retry on a decline it called preliminary.Two displays set it, one per fetch foundation, so it lives beside fetchInert rather than on either: HiC's contacts fetch declines until CoreGetInfo lands, and MultiSampleVariantBaseModel's fetchNeeded declines until sourcesBase does. Both have a reload() that wakes the prerequisite's autorun as well as their own.It has to be strictly narrower than the gate it explains. One that restates the gate's negation makes every decline a deferred one. No run is then ever judged, which exempts the display from the check. HiC does this deliberately, because its gate and its prerequisite are one condition; what covers its retry instead is LinearHicDisplay/infoFetchFailure.test.ts.Not for a display deliberately not fetching at all — that is fetchInert above, which the loading scrim and the export read too. | 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 |
Methods
| Member | Description | Defined by |
|---|---|---|
rpcProps() => LDRpcProps | SharedLDModel | |
columnX(column: number) => number | Viewport x of a position on the matrix's column axis, in fractional column indices: 0 is the triangle's left corner, i + 0.5 the apex of column i, i + 1 the boundary between columns i and i+1. The index-mode connector lines anchor through this.It rides the same forward transform the shader does — cellWidth (uniformW) is the payload's cell span in bp and viewTransform maps it to the live viewport, exactly like hitTest inverts it. Deriving the column pitch from the current block width instead applies the zoom twice, sliding everything anchored here off the triangle for the whole debounce+RPC window after a zoom. | SharedLDModel |
locusViewportX(refName: string, coord: number) => number | undefined | Viewport x of one locus, through the same locusViewportXFor the connector lines use. The crosshair ticks and the view's vertical guides go through this rather than measuring off contentBlocks[0]: that block's own left edge is only x=0 while the content reaches the viewport edge, and a SNP in any later block isn't measured against its own region at all. Undefined when the locus has no on-screen x, which the caller drops rather than pinning to 0. | SharedLDModel |
cellToScreen(x: number, y: number) => { x: number; y: number; } | Forward transform of the LD matrix (triangleDataToScreen), paired with hitTest below (its exact inverse): pre-rotation cell coordinates to canvas-relative pixels. The overlays that decorate individual cells — the hover crosshair, the focal-SNP band — place themselves through this, so they land on the cells the shader drew and move with the same rescale during the debounce+RPC window. | SharedLDModel |
screenToCell(mouseX: number, mouseY: number) => { x: number; y: number; } | The exact inverse of cellToScreen (triangleScreenToData), split out of hitTest so the pair is checkable as an identity rather than only through the cell it lands in — overlayCoords.test.ts asserts coordinates, so it catches a dropped term. | SharedLDModel |
hitTest(mouseX: number, mouseY: number) => LDFlatbushItem | undefined | Takes mouse coords (canvas-relative) and returns the LD cell under the cursor, or undefined: screenToCell above, then the boundary walk. Mirrors plugins/hic's hitTest so both contact maps keep the forward and inverse transforms paired on the model. | SharedLDModel |
svgLegendWidth() => number | The triangle fills its band, so the export parks the key beside it — see svgLegendGutterWidth for why it reserves on the setting alone. | SharedLDModel |
() => MenuItem[] | SharedLDModel | |
renderSvg(opts: ExportSvgDisplayOptions) => Promise<ReactNode> | SharedLDModel | |
| 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 |
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 |
Actions
| Member | Description | Defined by |
|---|---|---|
setRpcData(data: LDDataResult) => void | The shared commit stamps the signature this was fetched for (GlobalFetchMixin.commitFetchResult) in the same transaction. | SharedLDModel |
setFocalSnp(snp: LDSnp | undefined) => void | SharedLDModel | |
setLineZoneHeight(n: number) => void | SharedLDModel | |
setLDMetric(metric: LDMetric) => void | SharedLDModel | |
setShowLDTriangle(show: boolean) => void | SharedLDModel | |
setSquashToHeight(value: boolean) => void | SharedLDModel | |
setShowVerticalGuides(show: boolean) => void | SharedLDModel | |
setShowLabels(show: boolean) => void | SharedLDModel | |
setUseGenomicPositions(value: boolean) => void | SharedLDModel | |
startRenderingBackend(backend: LDRenderingBackend) => void | Starts the upload/render autorun. | SharedLDModel |
setStatusMessage(status?: RpcStatus | undefined) => void | BaseDisplay | |
setError(error?: unknown) => void | BaseDisplay | |
clearHoveredFeature() => void | Overridable hook (default no-op): drop whatever hoveredFeature reports. The writing twin of that getter, and what installClearHoverOnViewportChange calls.A display that STORES its hover owes an override; one that derives it from the live pointer (MAF, Hi-C, LD) owes nothing, and the default costs it nothing. Declared here so the clear can be installed for every display rather than remembered per display — forgetting it is the failure ARCHITECTURE.md's stored-hover section is about, and it used to be six closures at six call sites, which is six chances to omit one. | 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 |
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 |
commitFetchResult(commit: () => void, key: FetchKey) => void | The commit half of a keyed fetch: run the display's own store in the same transaction as the key stamp, so no observer can see fresh data under a stale key or the reverse. As the only writer of loadedFetchKey, this action makes dataCurrent derivable, because a display cannot commit without stamping. | KeyedFetchMixin |
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 |