Skip to content

Add feature density histogram when zoomed out - #873

Merged
garrettjstevens merged 15 commits into
mainfrom
feature-density
Oct 30, 2026
Merged

garrettjstevens merged 15 commits into
mainfrom
feature-density

Conversation

@garrettjstevens

Copy link
Copy Markdown
Contributor

Before, if a user zoomed out to more than 200 bp/px, a message appeared saying to zoom in to see the features. This was to prevent loading too many features and crashing the browser. There was also a setting to change this threshold.

Now, Apollo checks how many features have been requested, and if that's more than 200 (also configurable) it shows a density histogram instead. (Old zoom-level based threshold also still available).

Heres an example of being zoomed out to see all of chr1 on human data. The histogram is split by strand, and mousing over gives a summary of the bin. You can also click a bin to zoom in to it.

localhost_8999__config=http%3A%2F%2Flocalhost%3A3999%2Fjbrowse%2Fconfig json session=local-eI6PLVJ67r image

getFeatureCount filtered on start/end, but feature documents store their
range in min/max, so counts for a range never matched anything.

Assisted-by: Claude Code:claude-opus-5-5
Shared helpers for summarizing features in a region as a count plus a
histogram of how many features overlap each bin. Bins are aligned to
multiples of a "nice" bin size so they can be reused while panning.

Assisted-by: Claude Code:claude-opus-5-5
Returns the number of features overlapping a range and how many overlap
each bin of the range, computed with a single aggregation. Verified
against the in-memory computeFeatureDensity on random data, including
long and zero-length features.

Assisted-by: Claude Code:claude-opus-5-5
The collaboration server driver calls the new endpoint. The local driver
computes the same summary from IndexedDB, reading only each feature's
range instead of adding features to the client data store.

Assisted-by: Claude Code:claude-opus-5-5
Both Apollo linear displays now use a shared FeatureDensityMixin to
decide between rendering features and showing a density fallback.

- "auto" mode (the default) asks the backend how many features are in
  view and renders them if there are at most maxFeatureCount (default
  1000), so one long feature or sparse data can be shown zoomed out.
  Regions already known to be under the limit aren't checked again.
- "fixed" mode keeps the old behavior of switching at zoomThreshold bp
  per px.

A new "Feature display threshold" dialog replaces "Change zoom
threshold" and lets users choose between the modes. The settings are
also configuration slots on both displays. Until the histogram exists,
the fallback still shows the "Zoom in to see annotations" message.

Assisted-by: Claude Code:claude-opus-5-5
When there are too many features in view, both Apollo linear displays
now show a histogram of how many features overlap each bin instead of a
"Zoom in" message. A banner explains why and offers to show the features
anyway. Hovering a bar shows its range and count, and clicking it zooms
in 10x around it.

Assisted-by: Claude Code:claude-opus-5-5
Covers showing sparse features zoomed out past the old fixed threshold,
falling back to the histogram over the feature limit, "show them
anyway", and fixed zoom threshold mode.

Assisted-by: Claude Code:claude-opus-5-5
The client data store now counts applied changes, and the density
summary is fetched again when the count changes, so the histogram
reflects edits made locally or by collaborators.

Assisted-by: Claude Code:claude-opus-5-5
Prettier removes the parentheses that unicorn/no-nested-ternary asks
for, so render the alert, histogram, and features as separate
expressions instead.

Assisted-by: Claude Code:claude-opus-5-5
The autorun tracked the density key with a bare `void self.densityKey`,
which the bundler removes (treeshake.propertyReadSideEffects is false).
Zooming or panning while showing the histogram then never fetched new
stats. Pass the key to fetchDensityStats so the read is kept, and test
the autorun itself.

Assisted-by: Claude Code:claude-opus-5-5
JBrowse's track label overlaps the top left of the track and hid the
start of the banner.

Assisted-by: Claude Code:claude-opus-5-5
The histogram now stretches to the full track height instead of a fixed
80px, and has a count scale on its right edge (the track label covers the
left) with ticks at 1/2/5×10ⁿ steps. The scale replaces the "max per bar"
note in the banner.

Assisted-by: Claude Code:claude-opus-5-5
FeatureDensity gets an optional strandBins with forward, reverse, and
unstranded counts per bin. The server groups its aggregation by bin and
strand, and the local driver passes strands to computeFeatureDensity.
It's optional so clients still work with servers that don't send it.

Assisted-by: Claude Code:claude-opus-5-5
With strand counts, + bars grow up and − bars grow down from a center
line, each side ending with half of the unstranded count. The scale is
mirrored to match, a legend shows the strand colors, and the tooltip
gives the count on each strand. Without strand counts, bars are drawn
as before.

Assisted-by: Claude Code:claude-opus-5-5
The density count and histogram counted every top-level feature, even
ones hidden by the display's feature type filter, so the track could stay
on the histogram with few visible features in view. getFeatureDensity now
takes optional feature types (a repeatable "type" query parameter on the
server), and LinearApolloDisplay passes its filter. Cached under-limit
counts are only reused for the same or fewer types.

The six-frame display draws only gene-like features and doesn't apply its
type filter, so its density stays unfiltered.

Assisted-by: Claude Code:claude-opus-5-5
@garrettjstevens garrettjstevens self-assigned this Oct 29, 2026
@garrettjstevens
garrettjstevens merged commit d194737 into main Oct 30, 2026
10 checks passed
@garrettjstevens
garrettjstevens deleted the feature-density branch October 30, 2026 21:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant