Skip to content

feat(components): mutations over time: do not query mutations if explicit list is given#1100

Open
fhennig wants to merge 5 commits intomainfrom
optimize-mut-over-time-query
Open

feat(components): mutations over time: do not query mutations if explicit list is given#1100
fhennig wants to merge 5 commits intomainfrom
optimize-mut-over-time-query

Conversation

@fhennig
Copy link
Contributor

@fhennig fhennig commented Mar 19, 2026

resolves #1099

Problem

We always query for all mutations in the date range, and also for all their counts and coverage. This is quite an expensive call to make, with the current 200 Million covid sequences, for the whole date range, this takes about 3 seconds. We make this call also if we only request a single mutation.

Solution

The call was done for two reasons:

  1. To get the full list of mutations to query for, in case no explicit list was given by the user
  2. To get the total count and proportion for the mutations

For 1., we still query LAPIS to get the list; there is no way around this. But for 2., we can actually get all this data (counts, coverage) from the mutations-over-time call we make next. This PR does exactly that. Now for user provided mutation lists, we save the API call.

Tests, Screenshots

Some rows are now gone, some added, I skimmed it and it looks good to me. The changes are IMO because the calculations are sometimes slightly differently rounded? Or in some cases the data was edited manually anyways so two API calls don't correlate correctly.

PR Checklist

  • All necessary documentation has been adapted.
  • The implemented feature is covered by an appropriate test.
    • I updated the tests, the numbers show that we're actually aggregating
    • Also one test does an explicit request for include mutations, and there I've removed the API mock for the mutations call, and it is actually not called, which is what we'd expect!

@vercel

This comment was marked as off-topic.

@fengelniederhammer
Copy link
Collaborator

Ohoh, this might create merge conflicts with the lazy loading...

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR optimizes the “mutations over time” data fetch by avoiding an extra (expensive) {aminoAcid,nucleotide}Mutations request when the caller already provides an explicit mutation list, and instead derives overall counts/proportions from the subsequent mutationsOverTime response.

Changes:

  • Skip querying the full mutations list when displayMutations is provided; only query mutation codes when displayMutations is absent.
  • Compute overallMutationData (counts/proportions) from mutationsOverTime per-date count/coverage data instead of a separate mutations endpoint call.
  • Update Vitest expectations and Storybook/snapshot artifacts to reflect the new aggregation behavior.

Reviewed changes

Copilot reviewed 6 out of 17 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
components/src/query/queryMutationsOverTime.ts Removes overall mutations query for explicit lists; computes overall counts/proportions from over-time response; adds helper to query mutation codes only when needed.
components/src/query/queryMutationsOverTime.spec.ts Updates expectations and removes now-unnecessary mutations endpoint mocks for explicit mutation list tests.
components/src/preact/mutationsOverTime/mutations-over-time.stories.tsx Removes mocks for the now-skipped mutations call in stories with explicit displayMutations; adjusts initial interval to keep story stable.
components/src/lapisApi/lapisApi.ts Adds clarifying comment about the shape of the 2D data array returned by mutationsOverTime.
components/tests/snapshots.spec.ts-snapshots/Mutations-over-time-Story-visualization-mutati-ddeb1-rtion-on-small-screen-should-match-screenshot-1-chromium-linux.png Updated visual snapshot due to changed aggregation/output.
components/tests/snapshots.spec.ts-snapshots/Mutations-over-time-Story-visualization-mutati-c413d-ed-mutations-and-gaps-should-match-screenshot-1-chromium-linux.png Updated visual snapshot due to changed aggregation/output.
components/tests/snapshots.spec.ts-snapshots/Mutations-over-time-Story-visualization-mutati-5715b-n-displayed-mutations-should-match-screenshot-1-chromium-linux.png Updated visual snapshot due to changed aggregation/output.
components/tests/snapshots.spec.ts-snapshots/Mutations-over-time-Download-of-visualization-mutations-over-time--by-month-should-match-snapshot-1-firefox-linux.txt Updated download snapshot rows/values due to changed aggregation/output.
components/tests/snapshots.spec.ts-snapshots/Mutations-over-time-Download-of-visualization-mutations-over-time--by-month-should-match-snapshot-1-chromium-linux.txt Updated download snapshot rows/values due to changed aggregation/output.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +76 to +89
const mutationsToQuery =
displayMutations ??
(await queryAllMutationCodes({
lapisFilter,
requestedDateRanges,
sequenceType,
lapis,
lapisDateField,
signal,
}));
const sortedMutationCodes = mutationsToQuery
.map(parseMutationCode)
.sort((a, b) => sortSubstitutionsAndDeletions(a, b))
.map((m) => m.code);
Copy link

Copilot AI Mar 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

displayMutations values are now parsed via parseMutationCode for sorting. If a user provides an invalid mutation string, this will throw a generic Error and likely surface as an unhelpful runtime failure. Consider validating displayMutations up front and throwing a UserFacingError (or filtering out invalid codes) with a message that tells the user which entry is invalid and what formats are accepted.

Copilot uses AI. Check for mistakes.
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, it's not really a 'user' input per se, it's like if you misspelled the date field, it'll just error. IMO that's how we're doing things, so no change required?

Maybe we could add the parsing earlier, so we get the 'invalid component attributes' error, but I don't want to change more of the structure in the PR at the moment, because like Fabian said, we might already get merge conflicts the way it is.

But we could do it.

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.

Mutations over time: Mutations call can be omitted if the list of mutations is static

3 participants