statgen / locuszoom

A Javascript/d3 embeddable plugin for interactively visualizing statistical genetic data from customizable sources.
https://statgen.github.io/locuszoom/
MIT License
154 stars 29 forks source link

[refactor] Streamline rendering pipeline #211

Closed abought closed 3 years ago

abought commented 3 years ago

Larger items split from #208.

Purpose

The current LocusZoom rendering process has become convoluted as features have been added. Certain functions depend heavily on global state, and annotations and filtering were grafted on after the fact. This makes data layer rendering operations hard to debug or extend with new features. (eg #206 )

This ticket will track the refactor of the internal rendering logic, breaking it into conceptual pieces with a more functional style (where possible, have data passed around as function arguments instead of saved as global references).

Planned architecture

The rendering process will be broken into three phases:

  1. Data: retrieve the data from the adapter, then perform any adjustments needed for this data layer, such as:
    • Retrieve data from the adapter (this is done once per reMap; it is not done on every render)
    • Add synthetic fields (category scatter x position, gene extent, etc)
    • Generate basic summary info (like axis extents and scatter tick labels) from the full (not filtered) dataset
    • Some data layers might want to customize whether or not filters apply to tick labels
    • Apply user-filters to determine which data elements are eligible for rendering
    • After filtering, apply coalescing operations to limit rendered set based on viewable area (for performance optimizations)
    • Once the final set of rendered points is ready, apply "custom" fields and "data methods" used by rendering logic (generate references like getDataLayer, getPlot, toHTML; also cache frequently recomputed values like getElementId).
  2. Display phase
    • Clear any previous markings (labels, tooltips, etc)
    • Render elements, bounding boxes, & hitareas. Apply event listeners as appropriate.
    • Render markings (tooltips, labels) based on saved state. This should take the point annotation cache into account. (eg, user-selected labels)
  3. Interaction phase (updates that happen after initial render)
    • Respond to event listeners to apply point states such as "highlighted", "selected", "tooltip". Note that some interactions are "exclusive", so this needs to know about all states (not just the current element).
    • Apply special events such as "highlight matching items in another data layer"

TODO