LinearManhattanDisplay
Auto-generated @jbrowse/mobx-state-tree API for the current JBrowse release —
see pluggable elements for concepts. Provided by the
gwas plugin.
View source.
GWAS Manhattan-plot display drawing -log10 p-values as a scored scatter along the genome, with a 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('LinearManhattanDisplay') | LinearManhattanDisplay | |
configurationconfiguration: ConfigurationReference(configSchema) | LinearManhattanDisplay | |
indexSnpindexSnp: types.maybe(types.string) | Index/lead SNP for LD coloring — a SNP id or chr:bp (1-based) string. Auto-tracks the highest-scoring loaded SNP unless the user pins one (see indexSnpPinned). | LinearManhattanDisplay |
indexSnpPinnedindexSnpPinned: types.stripDefault(types.boolean, false) | True once the user pins a specific index SNP (right-clicking a point). While false, the index auto-tracks the top hit as data loads. | LinearManhattanDisplay |
idid: ElementId | BaseDisplay |
Volatiles
| Member | Description | Defined by |
|---|---|---|
rpcDataMaprpcDataMap: regionDataMap<ManhattanRpcResult>('rpcDataMap') | LinearManhattanDisplay | |
flatbushesflatbushes: regionDataMap<Flatbush>('flatbushes') | LinearManhattanDisplay | |
hoveredManhattanHithoveredManhattanHit: undefined as ManhattanHit | undefined | LinearManhattanDisplay | |
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') | regions whose data has been fetched and committed, keyed by displayedRegionIndex; populated only after the fetch work callback returns | 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 string | undefined | The viewport key the gate last asked the adapter about, on either axis. 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 |
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 |
activeStopTokenactiveStopToken: undefined as StopToken | undefined | stop token 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 both LGV fetch foundations compose, the same argument that put fetchInert below; the comparative family carries its own on SyntenyFetchStateMixin (ADR-054). | 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 createStopTokenRotation 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: createStopTokenRotation owns token 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 token. 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). 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 |
Getters
| Member | Description | Defined by |
|---|---|---|
hoveredFeatureManhattanHit | undefined | Fills BaseDisplay's cross-display hover hook. | LinearManhattanDisplay |
| conf | the config typed off the concrete schema; ConfigurationReference erases self.configuration to any, so reads route through this to stay typed | LinearManhattanDisplay |
prefersOffsetboolean | Offset the track label above the plot so the -log10(p) y-axis stays pinned to the content edge instead of dodging right of the label. | LinearManhattanDisplay |
colorstring | The color slot — a CSS color, or a jexl: expression — forwarded to the worker, which binds feature and evaluates it once per point (makeColorEvaluator).Reads the raw slot value, not getConf: this is a transport read, and getConf evaluates a callback against whatever context the call passes, which here is none. get(feature,…) against no feature throws reading 'get', and that escaped this getter and bannered the whole display. Pinned end-to-end by colorSlotTransport.test.ts. | LinearManhattanDisplay |
colorBy"ld" | "normal" | resolved coloring mode: 'normal' uses color, 'ld' colors by r² to the index SNP | LinearManhattanDisplay |
ldAdapterConfigRecord<string, unknown> | undefined | the PLINK .ld sub-adapter configured on the track's GWASAdapter, or undefined when none is set (the slot defaults to null, normalized here to undefined for "absent") | LinearManhattanDisplay |
hasLdDataboolean | LD coloring needs a configured .ld adapter; without one the colorBy='ld' controls are inert, so they're hidden/disabled | LinearManhattanDisplay |
ldColoringActiveboolean | LD coloring is actually in effect — the mode is on and there's an .ld adapter for it to read. colorBy alone can be 'ld' from config with no adapter configured, in which case the worker silently falls back to normal coloring, so every LD affordance (legend, missing-index warning) keys off this rather than off colorBy. | LinearManhattanDisplay |
showLdLegendboolean | Whether the LD color key is drawn. Resolved through the promotable-slot tiers (resolveConf): an explicit track value customizes it either way, otherwise it follows the session-wide default for this display type, falling back to on. Config-backed rather than volatile, which it was until this became a slot: a volatile reset on every retick, so turning the key off lasted until the track was hidden and reshown. It reads as a setting in the menu and now behaves like one. | LinearManhattanDisplay |
showLdLegendDisplayTypeDefaultPin | "make the current LD-key visibility the default for all tracks" control (pin): symmetric, so it promotes whichever value the track shows. | LinearManhattanDisplay |
significanceLinenumber | undefined | the configured threshold score, or undefined when the slot is unset | LinearManhattanDisplay |
domain[number, number] | undefined | nice-rounded [min, max] -log10 p domain across the visible regions, or undefined before any data loads. The only walker of the four that reads shipped per-region extremes rather than scanning scores: the worker already reduced them, so a block contributes its whole region's extremes rather than the part it shows. Widened to reach the significance line, the same way the wiggle displays widen theirs to reach a configured scoreRules entry. The threshold answers "does anything here clear it?", so the window where the answer is no — every score well under the line — is the one where an unwidened axis drops the line and leaves the reader nothing to read the plot against. widenRangeToRules applies to the raw range, so an explicit minScore/maxScore still wins. | LinearManhattanDisplay |
ticksYScaleTicks | undefined | y-axis tick positions. Manhattan plots are linear-only (pre-transformed -log10 p values); the inherited scaleType config is intentionally ignored so the axis ticks stay consistent with the linear domain. | LinearManhattanDisplay |
scoreRuleMarksScoreRuleMark[] | The threshold as a score rule, or [] when the slot is unset. Both the on-screen overlay and the SVG export take the line from here, so an exported figure cannot draw it at a different height than the screen did.A one-element read of the same scoreRuleMarks the wiggle displays place their configured rules with: this display's threshold is a rule at a chosen score, which is what that helper is. Manhattan pins its axis linear (see domain), so the normalizer is the linear one.The helper still drops a rule outside the domain, which here only happens where domain could not widen to it: an explicit minScore/maxScore bound that excludes the line. | LinearManhattanDisplay |
renderStateManhattanRenderState | render geometry for the inner canvas (between top/bottom YScaleBar label offsets) — the area both the GPU renderer and findManhattanHit work in. Using self.height directly would drift the hit-test off the rendered points. | LinearManhattanDisplay |
regionRefNamesReadonlyMap<number, string> | displayedRegionIndex → refName lookup. Hit-testing reads this on every mousemove; MobX caches the view so visibleRegions changes invalidate it once rather than rebuilding per event. | LinearManhattanDisplay |
topSnpstring | undefined | highest-scoring loaded SNP as a chr:bp (1-based) string — the default LD index SNP. Derived from loaded data (not a fetch input), so it's applied via the auto-pick autorun rather than read into rpcProps.Regions are scanned in ascending index order, not rpcDataMap insertion order, so ties break the same way every load. Exact ties at the top are routine — negLog10 clamps every underflowed p=0 to the same ~323.3 — and rpcDataMap is cleared and refilled in RPC-resolution order on each recolor. Adopting whichever tied SNP happened to land first would make topSnp flip between them, and since adopting it refetches, the display would livelock and never paint (see ldAutoIndex.test.ts). | LinearManhattanDisplay |
indexSnpMissingboolean | true when LD coloring is active with data loaded, but no region's LD data referenced the index SNP — so every point is grey. LD is a single-region analysis, so "found in no loaded region" means missing. | LinearManhattanDisplay |
indexSnpOffscreenboolean | When the index SNP is a chr:bp locus, whether it lies outside every visible region — the benign, pannable cause of indexSnpMissing (PLINK --ld-window files carry no records once you pan away from the index), as opposed to reference-name aliasing or the SNP being absent from the file. A bare rsID index returns false since its position isn't known here. | LinearManhattanDisplay |
dataSupersededboolean | Fills MultiRegionDisplayMixin's supersession hook: the loaded data was colored under an index SNP the auto-pick is about to replace with the top hit, so setIndexSnp — an rpcProps field — will clear it and refetch.The condition is the auto-pick's own, colorBy === 'ld' rather than ldColoringActive: what invalidates the load is the WRITE, and the autorun writes whether or not an ldAdapter is configured. Gating this on the adapter left colorBy: 'ld' with none — a config the getters above document as supported — exporting the empty lane this exists to prevent. On screen that is one invisible tick; an export samples svgReady once, and sampling it here captured the doomed load and painted the emptied map, which is a Manhattan lane with no points in it and the LD legend beside it. | LinearManhattanDisplay |
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 |
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; } | Overridable hook: which widget openFeatureWidget opens for one of this display's features. The default is the generic one, which is what a display drawing plain features wants and what the canvas base spelled out by hand.An override is a display whose features have a vocabulary of their own — a read, a variant, a synteny block — and the id is deliberately part of it: two displays naming one id share the drawer panel, which is the behaviour when the two are showing the same kind of thing. | 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. Reading it here is what makes self.resizing available to a display that did. | TrackHeightMixin |
scrollableHeightnumber | Overridable hook: how far this display's content can scroll past its viewport, in px. Infinity (the default) means "this display doesn't scroll internally" — setScrollTop then never clamps and the re-clamp autorun below is inert, so a non-scrolling display pays nothing and, crucially, never evaluates a getter that would read view geometry.A display that scrolls a canvas overrides this with max(0, contentHeight - viewportHeight), and gets the clamped setter plus the shrink autorun for free. It is the single "does it scroll, and by how much" answer: the wheel handler (useVirtualScrollWheel) and VerticalScrollbar read the same getter. | 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 |
canRenderboolean | Overrides RenderLifecycleMixin's default-true hook with the LGV precondition both foundations share — see foundationCanRender. | 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 alone: a phase that went loading on a moved regionFetchKey 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 |
layoutReadyboolean | Overridable hook (default false): whether a searchable feature layout currently exists. Any display defining a feature-lookup method (searchFeatureByID, getFeatureById) 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 |
regionFetchKeystring | Overridable hook (default ''): what a fetch issued right now would produce for a region, as a string — the display's per-region content axis. fetchRegions captures it before it issues the RPC and stamps it beside the loaded region; isCacheValid refetches a region whose stamp no longer matches. Wiggle returns String(view.bpPerPx) (adr-008), canvas the peptide-overlay threshold, the variant matrix its zoom in matrix mode only.NOT an rpcProps() field: this invalidates one region's held data where rpcProps invalidates all of it, and a zoom-swinging value in the RPC payload blanks the display at the force-load floor — see REGION_TOO_LARGE.md §"How the verdict is built".A getter, so the observables it reads register as dependencies of FetchVisibleRegions; MobX runs an action untracked and the autorun would keep a stale answer. | 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 |
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 this (not "the first datum arrived") is what keeps a multi-region/whole-genome export complete.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 regionFetchKey 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 still reads viewportWithinLoadedData alone: folding staleness into the phase raises the loading scrim into every zoom, which is the trade REJECTED_IDEAS.md "Folding content staleness into displayPhase" turned down and 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.Off the first LOADED region rather than the view's displayed ones, which is the distinction that makes it belong here: 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. Handing back undefined until it can answer is what makes the caller write its fallback. | 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 |
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 computeLoadingTerm reaches all three without being wired three times.This family's argument is spatial: loading also covers stale data (viewport past loaded) still on screen through the pre-refetch debounce. 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 |
gateEnabledboolean | The opt-in. Overridden with a literal true by gated displays, and check-gated-adapter-budgets insists on a literal: this mixin returns early on it in an autorun and in commitFetchBytes. | RegionTooLargeMixin |
densityGateEnabledboolean | Whether the density axis applies. CanvasFeatureGateMixin contributes true beside its measurement; byte-only displays leave it. | RegionTooLargeMixin |
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 | The display's fetchSizeLimit slot, from regionTooLargeConfigSchemaFields. | RegionTooLargeMixin |
densityTooLargeboolean | The density axis's verdict; canvas overrides it. | RegionTooLargeMixin |
byteGateAdapterPathstring[] | 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. 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. | RegionTooLargeMixin |
byteGateAdapterKeystring | Which tier the estimate is about, as a comparable string. | 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 is about a viewport the user has since left. True before any measurement. | 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 | gateActive plus the density axis's own terms: the axis is on, and the span is above the floor. | 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 |
rendersCanvasboolean | Overridable hook (default true): whether this display paints a canvas in its current configuration, as opposed to a deliberate static placeholder (LD with the triangle off, sequence past base resolution — both render a message where the <canvas> would go, so canvasRef is never called and canvasDrawn can never flip).Lives here, beside canvasDrawn, because every consumer of "has this display painted" needs the pair — and until 2026-08 each family declared its own copy (per-region hard-coded true, global carried the hook for LD), so a display could express the state only to whichever family it happened to compose. See painted below for the reader that was missed. | 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 saying otherwise is a lie that never resolves.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 burn its full timeout — silently, since that wait swallows its own. Same shape as fetchInert on the comparative side: the reader you forget 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. See that hook. | RenderLifecycleMixin |
isLoadingboolean | true while a fetch is active | FetchMixin |
isLoadingOrCanceledboolean | isLoading widened to cover a user-canceled load. This, not isLoading, is what a displayPhase loading term wants. cancelFetchByUser clears the stop token synchronously, so isLoading goes false the instant the user clicks Cancel — and the loading overlay that unmounts on it is carrying the Retry button, which is the only way back: the state is deliberately durable, so no autorun restarts the fetch on its own. A bare isLoading therefore reads as ready over a display that is stopped, empty and offering nothing.Arc read isLoading directly and had exactly that hole. It is a getter here so no family has to remember the second term. | 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, three readers, and that is the whole point — a display that grows such a state has one thing to say rather than three, and the reader it would have forgotten is always the one outside itself: - the loading scrim ( computeLoadingTerm), which otherwise parks over the placeholder, permanently once a cancel has been clicked; - the SVG export (computeSvgReady's extraTerminal), whose awaitSvgReady is an unbounded when, so one such display hangs the whole view's export; - the dev-only retry check (makeRetryContractCheck), which would otherwise report a dead Retry on a display correctly declining to load anything.It was 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 one of the three was hard-coded false on the global family for a while, which is how LD came to be able to express only half its own state. Same name and same meaning as SyntenyFetchStateMixin.fetchInert now, so the retry check reads one field across all three fetch families. ADR-082.A hook rather than a displayPhase override, because overriding the getter means restating the whole loading condition — which is how sequence came to hold a verbatim copy of the other terms, one git blame away from silently missing the next one added.It 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 |
awaitingPrerequisiteboolean | Overridable hook (default false), read only by the dev-only retry 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 say it, one per fetch foundation, which is why 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, so no run is ever judged and the display has silently opted out — an exemption by another name. HiC is in that shape 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 |
rpcPropsCacheKeystring | The RPC cache key both fetch foundations invalidate on: this display's rpcProps() payload serialized to a string. serializeRpcProps owns the why, including the silently-dead-axis corollary.Here, beside the two hooks above, for the same reason they are: it describes the display, and every foundation composes this mixin. The per-region family watches it from SettingsInvalidate and the global one from its fetch autorun's trigger list — one getter and one name, so the two cannot come to invalidate on different axes. The global side built its own local computed over the same function until 2026-08, which was the same value under a second spelling. | FetchMixin |
scatterPointSizenumber | WiggleScoreConfigMixin | |
displayCrossHatchesboolean | The configured cross-hatch setting. A config slot rather than a display prop — like scatterPointSize beside it — because a prop cannot be set from a config at all: MST drops a snapshot key the schema never declares, so demos/cgiab had asked for hatches on its CNV track and never got them. Read showCrossHatches below for what actually draws; this is the raw setting the menu toggles. | WiggleScoreConfigMixin |
isDensityModeboolean | Whether score maps to color instead of height. Each display overrides this from its own rendering-type table (density / multirowdensity); the base is false so this mixin's resolved getters below can key on it, the same override idiom autoscaleSourceNames uses in WiggleCommonMixin. | WiggleScoreConfigMixin |
showCrossHatchesboolean | Whether the score-axis cross hatches draw. Density spends color, not height, on the score, so there is no axis for them to rule — and the track menu drops the toggle there, which would strand hatches enabled in another plot type with no way to turn them off. Every consumer (on-screen overlay, multi-row overlay lines, SVG export) reads this, never the raw displayCrossHatches setting. | WiggleScoreConfigMixin |
scaleTypestring | ScoreScaleMixin | |
autoscaleTypestring | ScoreScaleMixin | |
numStdDevnumber | ScoreScaleMixin | |
minScorenumber | Raw slot value, sentinel intact — see the class comment. | ScoreScaleMixin |
maxScorenumber | Raw slot value, sentinel intact — see the class comment. | ScoreScaleMixin |
defaultScoreDomain[number | undefined, number | undefined] | Overridable hook: what each end of the domain falls back to where the config leaves its bound unset. [undefined, undefined] — the default — means autoscale both ends, which is right for a track whose scores have no absolute meaning (a bigwig's units are its own).A display whose scores are bounded by construction overrides it, so the axis stops being a function of what happens to be on screen: GC content is a fraction, so 0 and 1 are its real limits and mean the same thing at every locus. Autoscaled, the same GC value drew at different heights depending on where the user had panned, and the track could not be read across loci. A hook rather than a config default because the answer can depend on display state — GC's does, on gcMode — and rather than each display re-resolving the sentinels below, which is the one thing that must not be duplicated: config bounds still win, precisely because they are checked before this is consulted. | ScoreScaleMixin |
minScoreBoundnumber | undefined | Resolved lower bound; undefined means autoscale this end. | ScoreScaleMixin |
maxScoreBoundnumber | undefined | Resolved upper bound; undefined means autoscale this end. | ScoreScaleMixin |
Methods
| Member | Description | Defined by |
|---|---|---|
| rpcProps | fetch inputs watched by SettingsInvalidate — any change (color, colorBy, index SNP, LD adapter) triggers a refetch, since the worker bakes per-feature color into the result | LinearManhattanDisplay |
| Manhattan track menu: shared Score submenu plus LD-coloring controls. Rendering type / Resolution / Scale type don't apply to single-point rendering of pre-transformed -log10 p values. Placed after the color/index actions so referencing them doesn't make MST inference circular. | LinearManhattanDisplay | |
(hit: ManhattanHit) => MenuItem[] | right-click menu for a clicked point: feature details plus, when an LD adapter is configured, a shortcut to recolor by LD to that SNP | LinearManhattanDisplay |
| 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 |
regionHasData(_displayedRegionIndex: number) => boolean | Overridable hook (default true): whether the display can actually draw what this region is marked loaded over. Two different displays want it for two different reasons, and both are real: - The reader-side check of the write-side rule. loadedRegions is written where the payload is stored (RegionFetchContext), so an entry with nothing behind it means that rule was broken somewhere. Answering off the data map costs a lookup and decides which way the break fails: a refetch, or a viewport that reads as covered against data nobody has and never asks again. Both canvas displays. - Which of several held payloads answers. MAF caches a summary tier and a detail tier side by side under one displayedRegionIndex, so crossing the threshold inside an already-loaded region changes which map has to answer — something the coverage bounds cannot see at all.Separate from regionFetchKey on purpose: for MAF a key would refetch the summary on every zoom back out, since both tiers are still held. And the mixin cannot see a display's data map, so a key that changed when data arrived would be the rpcProps() loop in different clothes.The fail-open default is load-bearing, not an omission. A byte-gate refusal never marks a region loaded (the commit sits beside the store and skips refused results), so "marked loaded with nothing behind it" is unreachable from the gate — the one path that stamps without storing is sequence's legitimately-empty-region answer, and a store-derived default there would refetch forever: stamp, store nothing, read uncovered, fetch again. true is what lets "this fetch completed and there is genuinely nothing here" be a terminal state.A view, not an action, for the reason regionFetchKey is a getter. | MultiRegionDisplayMixin |
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 regionFetchKey (what a fetch now would produce) and regionHasData (did the last one store anything), and this compares the key against the one the region was fetched under. A subclass that changes what it fetches spells the change in the key, and one that forgets gets a redundant fetch rather than a cached answer for a zoom the data was never fetched at. | 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 |
Actions
| Member | Description | Defined by |
|---|---|---|
selectFeature(hit: ManhattanHit) => void | open the feature details widget for a clicked point | LinearManhattanDisplay |
setRpcData(idx: number, data: ManhattanRpcResult) => void | LinearManhattanDisplay | |
setHoveredFeature(hit: ManhattanHit | undefined) => void | LinearManhattanDisplay | |
setShowLdLegend(val: boolean) => void | LinearManhattanDisplay | |
setColorBy(mode: "ld" | "normal") => void | LinearManhattanDisplay | |
setSignificanceLine(score?: number | undefined) => void | Score to draw the threshold line at; undefined removes it. | LinearManhattanDisplay |
setIndexSnp(snp?: string | undefined) => void | LinearManhattanDisplay | |
colorByLdToHit(hit: ManhattanHit) => void | right-click "Color by LD to this SNP": switch into LD mode and pin the index on the clicked point, so the auto-pick stops tracking the top hit. Keyed by chr:bp (1-based) to match the worker's posKey. All mutations happen in one action so rpcProps settles once and only a single recolor fetch fires. | LinearManhattanDisplay |
useTopHitAsIndex() => void | release a pinned index back to auto-tracking, seeded at the current top hit (the auto-pick autorun then keeps it on the top hit as data loads) | LinearManhattanDisplay |
clearDisplaySpecificData() => void | LinearManhattanDisplay | |
| fetchNeeded | LinearManhattanDisplay | |
startRenderingBackend(backend: ManhattanRenderingBackend) => void | identity encode — RPC result is the upload payload | LinearManhattanDisplay |
| renderSvg | LinearManhattanDisplay | |
clearHoveredFeature() => void | Fills BaseDisplay's hover-clear hook, which the fetch foundation's reaction calls on every viewport change.The hover highlight is a DOM ring positioned from the hit's screenX/screenY, captured when the pointer last moved — so a pan/zoom/scroll under a stationary cursor (none of which fires a mousemove over a painted canvas) leaves it parked on empty space while the tooltip beside it describes a SNP that has moved. All three axes, not just bpPerPx: see installClearHoverOnViewportChange. | LinearManhattanDisplay |
setStatusMessage(status?: RpcStatus | undefined) => void | BaseDisplay | |
setError(error?: unknown) => void | BaseDisplay | |
reload() => void | base display reload does nothing, see specialized displays for details | BaseDisplay |
setScrollTop(scrollTop: number) => void | Clamped into [0, scrollableHeight], so no caller has to remember the bound. Unbounded for a display that leaves scrollableHeight at its Infinity default. | TrackHeightMixin |
setHeight(displayHeight: number) => number | TrackHeightMixin | |
resizeHeight(distance: number) => number | TrackHeightMixin | |
expandToContentHeight() => number | Grow the track by exactly the content it is currently hiding, so a display scrolled over a taller stack ends up showing all of it. The track's resize handle runs this on a double click.scrollableHeight is the whole measurement — it is already every scrolling display's answer to "how much is off the bottom", so no display has to supply a second one. A display that doesn't scroll internally leaves it at Infinity and gets a no-op, as does one already showing everything (0).Routed through resizeHeight rather than setHeight so grow mode's override still gets to leave grow first; going straight to the slot would let the reactive height re-derive grownHeight and the double click would appear to do nothing. | TrackHeightMixin |
| setLoadedRegion | The raw write behind ctx.commitRegion, and not what a fetch should call: a display naming its own span is the bug this family spent a release on, and going through the context is what makes that inexpressible — see RegionFetchContext. Direct callers are tests staging an already-loaded display.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 |
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 |
| 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 |
| setByteEstimate | The bytes half of a measurement alone, for a test staging a display. Production commits through commitFetchBytes. | RegionTooLargeMixin |
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 goes on voting for a phase that is over. The viewport fetch ( runFetch), the clustering run and a lent createStopTokenRotation are three of them on one field; before ADR-081 each blanked the field outright and the last one to finish decided what the other two were still saying.isCurrent is required and has no "node is alive" default, because alive is not the interesting question: 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(), which is what every display gets for free through ctx.statusCallback; 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.Declared this early only so runFetch can put one on every FetchContext. | 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 | Release an in-flight fetch's stop token 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 |
endFetch(current: boolean, stopToken: StopToken) => 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: whoever superseded it — a newer begin, or cancel — already released this token. | 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 stopToken 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 activeStopToken, 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 |
toggleCrossHatches() => void | WiggleScoreConfigMixin | |
setScatterPointSize(val?: number | undefined) => void | WiggleScoreConfigMixin | |
setScaleType(scaleType: string) => void | ScoreScaleMixin | |
setAutoscale(val?: string | undefined) => void | ScoreScaleMixin | |
setMinScore(val?: number | undefined) => void | ScoreScaleMixin | |
setMaxScore(val?: number | undefined) => void | ScoreScaleMixin |