@genspectrum/dashboard-components 1.12.0 → 1.13.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (57) hide show
  1. package/README.md +0 -7
  2. package/custom-elements.json +6 -25
  3. package/dist/components.d.ts +30 -36
  4. package/dist/components.js +943 -757
  5. package/dist/components.js.map +1 -1
  6. package/dist/util.d.ts +46 -30
  7. package/package.json +1 -5
  8. package/src/lapisApi/lapisApi.ts +21 -1
  9. package/src/lapisApi/lapisTypes.ts +36 -0
  10. package/src/preact/components/annotated-mutation.tsx +2 -2
  11. package/src/preact/{mutationsOverTime/mutations-over-time-grid.tsx → components/features-over-time-grid.tsx} +45 -52
  12. package/src/preact/genomeViewer/genome-data-viewer.tsx +2 -2
  13. package/src/preact/mutationsOverTime/MutationOverTimeData.ts +6 -4
  14. package/src/preact/mutationsOverTime/__mockData__/aminoAcidMutationsByDay/aminoAcidMutations.json +5482 -0
  15. package/src/preact/mutationsOverTime/__mockData__/aminoAcidMutationsByDay/aminoAcidMutationsOverTime.json +5496 -0
  16. package/src/preact/mutationsOverTime/__mockData__/byWeek/mutationsOverTime.json +7100 -0
  17. package/src/preact/mutationsOverTime/__mockData__/byWeek/nucleotideMutations.json +10122 -0
  18. package/src/preact/mutationsOverTime/__mockData__/defaultMockData/mutationsOverTime.json +12646 -0
  19. package/src/preact/mutationsOverTime/__mockData__/defaultMockData/nucleotideMutations.json +12632 -0
  20. package/src/preact/mutationsOverTime/__mockData__/request1800s/mutationsOverTime.json +16 -0
  21. package/src/preact/mutationsOverTime/__mockData__/request1800s/nucleotideMutations.json +11 -0
  22. package/src/preact/mutationsOverTime/__mockData__/withDisplayMutations/mutationsOverTime.json +52 -0
  23. package/src/preact/mutationsOverTime/getFilteredMutationsOverTime.spec.ts +3 -3
  24. package/src/preact/mutationsOverTime/mutations-over-time-grid-tooltip.tsx +3 -6
  25. package/src/preact/mutationsOverTime/mutations-over-time.stories.tsx +199 -12
  26. package/src/preact/mutationsOverTime/mutations-over-time.tsx +30 -35
  27. package/src/preact/wastewater/mutationsOverTime/wastewater-mutations-over-time.tsx +30 -3
  28. package/src/query/queryDatesInDataset.ts +89 -0
  29. package/src/query/queryMutationsOverTime.spec.ts +526 -548
  30. package/src/query/queryMutationsOverTime.ts +21 -232
  31. package/src/query/queryQueriesOverTime.spec.ts +432 -0
  32. package/src/query/queryQueriesOverTime.ts +125 -0
  33. package/src/utilEntrypoint.ts +3 -1
  34. package/src/utils/mutations.spec.ts +6 -0
  35. package/src/utils/mutations.ts +1 -1
  36. package/src/utils/temporalClass.ts +4 -0
  37. package/src/web-components/visualization/gs-mutations-over-time.spec-d.ts +0 -3
  38. package/src/web-components/visualization/gs-mutations-over-time.stories.ts +283 -17
  39. package/src/web-components/visualization/gs-mutations-over-time.tsx +0 -9
  40. package/standalone-bundle/dashboard-components.js +8935 -8781
  41. package/standalone-bundle/dashboard-components.js.map +1 -1
  42. package/dist/assets/mutationOverTimeWorker-f8Kp0S6V.js.map +0 -1
  43. package/src/preact/mutationsOverTime/__mockData__/aminoAcidMutationsByDay.ts +0 -47170
  44. package/src/preact/mutationsOverTime/__mockData__/byWeek.ts +0 -54026
  45. package/src/preact/mutationsOverTime/__mockData__/defaultMockData.ts +0 -108385
  46. package/src/preact/mutationsOverTime/__mockData__/mockConversion.ts +0 -54
  47. package/src/preact/mutationsOverTime/__mockData__/noDataWhenNoMutationsAreInFilter.ts +0 -23
  48. package/src/preact/mutationsOverTime/__mockData__/noDataWhenThereAreNoDatesInFilter.ts +0 -23
  49. package/src/preact/mutationsOverTime/__mockData__/showsMessageWhenTooManyMutations.ts +0 -65527
  50. package/src/preact/mutationsOverTime/__mockData__/withDisplayMutations.ts +0 -352
  51. package/src/preact/mutationsOverTime/__mockData__/withGaps.ts +0 -298
  52. package/src/preact/mutationsOverTime/mutationOverTimeWorker.mock.ts +0 -33
  53. package/src/preact/mutationsOverTime/mutationOverTimeWorker.ts +0 -29
  54. package/src/preact/webWorkers/useWebWorker.ts +0 -74
  55. package/src/preact/webWorkers/workerFunction.ts +0 -30
  56. package/src/query/queryMutationsOverTimeNewEndpoint.spec.ts +0 -988
  57. package/standalone-bundle/assets/mutationOverTimeWorker-AhhjjklP.js.map +0 -1
@@ -1,48 +1,20 @@
1
- import { mapDateToGranularityRange } from './queryAggregatedDataOverTime';
1
+ import { queryDatesInDataset } from './queryDatesInDataset';
2
2
  import { fetchMutationsOverTime } from '../lapisApi/lapisApi';
3
- import { FetchAggregatedOperator } from '../operator/FetchAggregatedOperator';
4
3
  import { FetchSubstitutionsOrDeletionsOperator } from '../operator/FetchSubstitutionsOrDeletionsOperator';
5
- import { GroupByAndSumOperator } from '../operator/GroupByAndSumOperator';
6
- import { MapOperator } from '../operator/MapOperator';
7
- import { RenameFieldOperator } from '../operator/RenameFieldOperator';
8
- import { SortOperator } from '../operator/SortOperator';
9
4
  import { UserFacingError } from '../preact/components/error-display';
10
5
  import { BaseMutationOverTimeDataMap } from '../preact/mutationsOverTime/MutationOverTimeData';
11
6
  import { sortSubstitutionsAndDeletions } from '../preact/shared/sort/sortSubstitutionsAndDeletions';
12
7
  import {
13
- type DeletionEntry,
14
8
  type LapisFilter,
15
9
  type SequenceType,
16
- type SubstitutionEntry,
17
10
  type SubstitutionOrDeletionEntry,
18
11
  type TemporalGranularity,
19
12
  } from '../types';
20
13
  import { type Map2DContents } from '../utils/map2d';
21
- import {
22
- type Deletion,
23
- type Substitution,
24
- toSubstitutionOrDeletion,
25
- DeletionClass,
26
- SubstitutionClass,
27
- } from '../utils/mutations';
28
- import {
29
- compareTemporal,
30
- dateRangeCompare,
31
- generateAllInRange,
32
- getMinMaxTemporal,
33
- parseDateStringToTemporal,
34
- type Temporal,
35
- type TemporalClass,
36
- toTemporal,
37
- } from '../utils/temporalClass';
38
-
39
- export type MutationOverTimeData = {
40
- date: TemporalClass;
41
- mutations: SubstitutionOrDeletionEntry[];
42
- totalCount: number;
43
- };
14
+ import { type Deletion, type Substitution, DeletionClass, SubstitutionClass } from '../utils/mutations';
15
+ import { type Temporal } from '../utils/temporalClass';
44
16
 
45
- export type MutationOverTimeMutationValue =
17
+ export type ProportionValue =
46
18
  | {
47
19
  type: 'value';
48
20
  proportion: number;
@@ -65,7 +37,7 @@ export type MutationOverTimeMutationValue =
65
37
  }
66
38
  | null;
67
39
 
68
- export function getProportion(value: MutationOverTimeMutationValue) {
40
+ export function getProportion(value: ProportionValue) {
69
41
  switch (value?.type) {
70
42
  case 'value':
71
43
  case 'wastewaterValue':
@@ -130,7 +102,7 @@ async function queryOverallMutationData({
130
102
  includeMutations?: string[];
131
103
  signal?: AbortSignal;
132
104
  }) {
133
- const requestedDateRanges = await getDatesInDataset(lapisFilter, lapis, granularity, lapisDateField, signal);
105
+ const requestedDateRanges = await queryDatesInDataset(lapisFilter, lapis, granularity, lapisDateField, signal);
134
106
 
135
107
  if (requestedDateRanges.length === 0) {
136
108
  if (includeMutations) {
@@ -170,22 +142,16 @@ async function queryOverallMutationData({
170
142
  return dataPromise;
171
143
  }
172
144
 
173
- export type MutationOverTimeQuery = {
174
- lapisFilter: LapisFilter;
175
- displayMutations?: string[];
176
- sequenceType: SequenceType;
177
- lapis: string;
178
- lapisDateField: string;
179
- granularity: TemporalGranularity;
180
- useNewEndpoint?: boolean;
181
- signal?: AbortSignal;
182
- };
183
-
184
- export async function queryMutationsOverTimeData(query: MutationOverTimeQuery) {
185
- const { lapisFilter, displayMutations, sequenceType, lapis, lapisDateField, granularity, useNewEndpoint, signal } =
186
- query;
187
-
188
- const requestedDateRanges = await getDatesInDataset(lapisFilter, lapis, granularity, lapisDateField, signal);
145
+ export async function queryMutationsOverTimeData(
146
+ lapisFilter: LapisFilter,
147
+ sequenceType: SequenceType,
148
+ lapis: string,
149
+ lapisDateField: string,
150
+ granularity: TemporalGranularity,
151
+ displayMutations?: string[],
152
+ signal?: AbortSignal,
153
+ ) {
154
+ const requestedDateRanges = await queryDatesInDataset(lapisFilter, lapis, granularity, lapisDateField, signal);
189
155
 
190
156
  if (requestedDateRanges.length > MAX_NUMBER_OF_GRID_COLUMNS) {
191
157
  throw new UserFacingError(
@@ -196,7 +162,7 @@ export async function queryMutationsOverTimeData(query: MutationOverTimeQuery) {
196
162
  );
197
163
  }
198
164
 
199
- const overallMutationData = queryOverallMutationData({
165
+ const overallMutationData = await queryOverallMutationData({
200
166
  lapisFilter,
201
167
  sequenceType,
202
168
  lapis,
@@ -205,56 +171,6 @@ export async function queryMutationsOverTimeData(query: MutationOverTimeQuery) {
205
171
  granularity,
206
172
  }).then((r) => r.content);
207
173
 
208
- return useNewEndpoint === true
209
- ? queryMutationsOverTimeDataDirectEndpoint(requestedDateRanges, overallMutationData, query)
210
- : queryMutationsOverTimeDataMultiQuery(requestedDateRanges, overallMutationData, query);
211
- }
212
-
213
- async function queryMutationsOverTimeDataMultiQuery(
214
- allDates: TemporalClass[],
215
- overallMutationDataPromise: Promise<SubstitutionOrDeletionEntry[]>,
216
- { lapisFilter, sequenceType, lapis, lapisDateField, signal }: MutationOverTimeQuery,
217
- ) {
218
- const subQueries = allDates.map(async (date) => {
219
- const dateFrom = date.firstDay.toString();
220
- const dateTo = date.lastDay.toString();
221
-
222
- const filter = {
223
- ...lapisFilter,
224
- [`${lapisDateField}From`]: dateFrom,
225
- [`${lapisDateField}To`]: dateTo,
226
- };
227
-
228
- const [data, totalCountQuery] = await Promise.all([
229
- fetchAndPrepareSubstitutionsOrDeletions(filter, sequenceType).evaluate(lapis, signal),
230
- getTotalNumberOfSequencesInDateRange(filter).evaluate(lapis, signal),
231
- ]);
232
-
233
- return {
234
- date,
235
- mutations: data.content,
236
- totalCount: totalCountQuery.content[0].count,
237
- };
238
- });
239
-
240
- const data = await Promise.all(subQueries);
241
- const overallMutationData = await overallMutationDataPromise;
242
-
243
- return {
244
- mutationOverTimeData: groupByMutation(data, overallMutationData),
245
- overallMutationData,
246
- };
247
- }
248
-
249
- async function queryMutationsOverTimeDataDirectEndpoint(
250
- allDates: TemporalClass[],
251
- overallMutationDataPromise: Promise<SubstitutionOrDeletionEntry[]>,
252
- { lapisFilter, sequenceType, lapis, lapisDateField, signal }: MutationOverTimeQuery,
253
- ): Promise<{
254
- mutationOverTimeData: BaseMutationOverTimeDataMap;
255
- overallMutationData: SubstitutionOrDeletionEntry[];
256
- }> {
257
- const overallMutationData = await overallMutationDataPromise;
258
174
  overallMutationData.sort((a, b) => sortSubstitutionsAndDeletions(a.mutation, b.mutation));
259
175
 
260
176
  const includeMutations = overallMutationData.map((value) => value.mutation.code);
@@ -262,7 +178,7 @@ async function queryMutationsOverTimeDataDirectEndpoint(
262
178
  lapis,
263
179
  {
264
180
  filters: lapisFilter,
265
- dateRanges: allDates.map((date) => ({
181
+ dateRanges: requestedDateRanges.map((date) => ({
266
182
  dateFrom: date.firstDay.toString(),
267
183
  dateTo: date.lastDay.toString(),
268
184
  })),
@@ -295,14 +211,14 @@ async function queryMutationsOverTimeDataDirectEndpoint(
295
211
  }
296
212
  });
297
213
 
298
- const mutationOverTimeData: Map2DContents<Substitution | Deletion, Temporal, MutationOverTimeMutationValue> = {
214
+ const mutationOverTimeData: Map2DContents<Substitution | Deletion, Temporal, ProportionValue> = {
299
215
  keysFirstAxis: new Map(responseMutations.map((mutation) => [mutation.code, mutation])),
300
- keysSecondAxis: new Map(allDates.map((date) => [date.dateString, date])),
216
+ keysSecondAxis: new Map(requestedDateRanges.map((date) => [date.dateString, date])),
301
217
  data: new Map(
302
218
  responseMutations.map((mutation, i) => [
303
219
  mutation.code,
304
220
  new Map(
305
- allDates.map((date, j): [string, MutationOverTimeMutationValue] => {
221
+ requestedDateRanges.map((date, j): [string, ProportionValue] => {
306
222
  if (totalCounts[j] === 0) {
307
223
  return [date.dateString, null];
308
224
  }
@@ -353,75 +269,6 @@ function parseMutationCode(code: string): SubstitutionClass | DeletionClass {
353
269
  throw Error(`Given code is not valid: ${code}`);
354
270
  }
355
271
 
356
- /**
357
- * Returns a list of date ranges as TemporalClass.
358
- * Respects date range filters given in the lapisFilter as <lapisDateField>From and <lapisDateField>To.
359
- * If either side (or both sides) of the range are not given, the min and max are determined from
360
- * the available data.
361
- */
362
- async function getDatesInDataset(
363
- lapisFilter: LapisFilter,
364
- lapis: string,
365
- granularity: TemporalGranularity,
366
- lapisDateField: string,
367
- signal: AbortSignal | undefined,
368
- ) {
369
- const { dateFrom, dateTo } = getDateRangeFromFilter(lapisFilter, lapisDateField, granularity);
370
- if (dateFrom !== null && dateTo !== null) {
371
- return generateAllInRange(dateFrom, dateTo);
372
- }
373
-
374
- const { content: availableDates } = await queryAvailableDates(
375
- lapisFilter,
376
- lapis,
377
- granularity,
378
- lapisDateField,
379
- signal,
380
- );
381
-
382
- const { min, max } = getMinMaxTemporal(availableDates);
383
-
384
- return generateAllInRange(dateFrom ?? min, dateTo ?? max);
385
- }
386
-
387
- function getDateRangeFromFilter(lapisFilter: LapisFilter, lapisDateField: string, granularity: TemporalGranularity) {
388
- const valueFromFilter = lapisFilter[lapisDateField] as string | null;
389
-
390
- if (valueFromFilter) {
391
- return {
392
- dateFrom: parseDateStringToTemporal(valueFromFilter, granularity),
393
- dateTo: parseDateStringToTemporal(valueFromFilter, granularity),
394
- };
395
- }
396
-
397
- const minFromFilter = lapisFilter[`${lapisDateField}From`] as string | null;
398
- const maxFromFilter = lapisFilter[`${lapisDateField}To`] as string | null;
399
-
400
- return {
401
- dateFrom: minFromFilter ? parseDateStringToTemporal(minFromFilter, granularity) : null,
402
- dateTo: maxFromFilter ? parseDateStringToTemporal(maxFromFilter, granularity) : null,
403
- };
404
- }
405
-
406
- function queryAvailableDates(
407
- lapisFilter: LapisFilter,
408
- lapis: string,
409
- granularity: TemporalGranularity,
410
- lapisDateField: string,
411
- signal?: AbortSignal,
412
- ) {
413
- return fetchAndPrepareDates(lapisFilter, granularity, lapisDateField).evaluate(lapis, signal);
414
- }
415
-
416
- function fetchAndPrepareDates(filter: LapisFilter, granularity: TemporalGranularity, lapisDateField: string) {
417
- const fetchData = new FetchAggregatedOperator<Record<string, string | null>>(filter, [lapisDateField]);
418
- const dataWithFixedDateKey = new RenameFieldOperator(fetchData, lapisDateField, 'date');
419
- const mapData = new MapOperator(dataWithFixedDateKey, (data) => mapDateToGranularityRange(data, granularity));
420
- const groupByData = new GroupByAndSumOperator(mapData, 'dateRange', 'count');
421
- const sortData = new SortOperator(groupByData, dateRangeCompare);
422
- return new MapOperator(sortData, (data) => data.dateRange);
423
- }
424
-
425
272
  function fetchAndPrepareSubstitutionsOrDeletions(filter: LapisFilter, sequenceType: SequenceType) {
426
273
  return new FetchSubstitutionsOrDeletionsOperator(filter, sequenceType, MUTATIONS_OVER_TIME_MIN_PROPORTION);
427
274
  }
@@ -433,61 +280,3 @@ export function serializeSubstitutionOrDeletion(mutation: Substitution | Deletio
433
280
  export function serializeTemporal(date: Temporal) {
434
281
  return date.dateString;
435
282
  }
436
-
437
- export function groupByMutation(
438
- data: MutationOverTimeData[],
439
- overallMutationData: (SubstitutionEntry | DeletionEntry)[],
440
- ): BaseMutationOverTimeDataMap {
441
- const dataArray = new BaseMutationOverTimeDataMap();
442
-
443
- const allDates = data.map((mutationData) => mutationData.date);
444
-
445
- const sortedOverallMutationData = overallMutationData
446
- .sort((a, b) => sortSubstitutionsAndDeletions(a.mutation, b.mutation))
447
- .map((entry) => {
448
- return toSubstitutionOrDeletion(entry.mutation);
449
- });
450
- const sortedDates = allDates.sort((a, b) => compareTemporal(a, b)).map((date) => toTemporal(date));
451
-
452
- sortedOverallMutationData.forEach((mutationData) => {
453
- sortedDates.forEach((date) => {
454
- dataArray.set(mutationData, date, null);
455
- });
456
- });
457
-
458
- data.forEach((mutationData) => {
459
- if (mutationData.totalCount == 0) {
460
- return;
461
- }
462
-
463
- const date = toTemporal(mutationData.date);
464
-
465
- mutationData.mutations.forEach((mutationEntry) => {
466
- const mutation = toSubstitutionOrDeletion(mutationEntry.mutation);
467
-
468
- if (dataArray.get(mutation, date) !== undefined) {
469
- dataArray.set(mutation, date, {
470
- type: 'value',
471
- count: mutationEntry.count,
472
- proportion: mutationEntry.proportion,
473
- totalCount: mutationData.totalCount,
474
- });
475
- }
476
- });
477
-
478
- for (const firstAxisKey of dataArray.getFirstAxisKeys()) {
479
- if (dataArray.get(firstAxisKey, date) === null) {
480
- dataArray.set(firstAxisKey, date, {
481
- type: 'belowThreshold',
482
- totalCount: mutationData.totalCount,
483
- });
484
- }
485
- }
486
- });
487
-
488
- return dataArray;
489
- }
490
-
491
- function getTotalNumberOfSequencesInDateRange(filter: LapisFilter) {
492
- return new FetchAggregatedOperator<{ count: number }>(filter);
493
- }