@genspectrum/dashboard-components 0.5.3 → 0.5.5

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 (40) hide show
  1. package/custom-elements.json +322 -0
  2. package/dist/dashboard-components.js +609 -265
  3. package/dist/dashboard-components.js.map +1 -1
  4. package/dist/genspectrum-components.d.ts +78 -0
  5. package/package.json +1 -1
  6. package/src/lapisApi/ReferenceGenome.ts +2 -0
  7. package/src/preact/aggregatedData/aggregate.tsx +2 -14
  8. package/src/preact/dateRangeSelector/date-range-selector.tsx +2 -14
  9. package/src/preact/locationFilter/location-filter.tsx +2 -7
  10. package/src/preact/mutationComparison/mutation-comparison.tsx +2 -10
  11. package/src/preact/mutationFilter/mutation-filter-info.tsx +117 -0
  12. package/src/preact/mutationFilter/mutation-filter.tsx +2 -2
  13. package/src/preact/mutationFilter/sequenceTypeFromSegment.spec.ts +1 -1
  14. package/src/preact/mutationFilter/sequenceTypeFromSegment.ts +2 -2
  15. package/src/preact/mutations/mutations.tsx +2 -10
  16. package/src/preact/numberSequencesOverTime/__mockData__/oneVariantEG.json +1702 -0
  17. package/src/preact/numberSequencesOverTime/__mockData__/twoVariantsEG.json +1710 -0
  18. package/src/preact/numberSequencesOverTime/__mockData__/twoVariantsJN1.json +1070 -0
  19. package/src/preact/numberSequencesOverTime/__mockData__/twoVariantsXBB.json +506 -0
  20. package/src/preact/numberSequencesOverTime/getNumberOfSequencesOverTimeTableData.spec.ts +75 -0
  21. package/src/preact/numberSequencesOverTime/getNumberOfSequencesOverTimeTableData.ts +39 -0
  22. package/src/preact/numberSequencesOverTime/number-sequences-over-time-bar-chart.tsx +58 -0
  23. package/src/preact/numberSequencesOverTime/number-sequences-over-time-table.tsx +32 -0
  24. package/src/preact/numberSequencesOverTime/number-sequences-over-time.stories.tsx +133 -0
  25. package/src/preact/numberSequencesOverTime/number-sequences-over-time.tsx +105 -0
  26. package/src/preact/prevalenceOverTime/prevalence-over-time-bar-chart.tsx +11 -20
  27. package/src/preact/prevalenceOverTime/prevalence-over-time.tsx +2 -20
  28. package/src/preact/relativeGrowthAdvantage/relative-growth-advantage.tsx +2 -14
  29. package/src/preact/textInput/text-input.tsx +2 -2
  30. package/src/query/queryAggregatedDataOverTime.ts +78 -0
  31. package/src/query/queryNumberOfSequencesOverTime.spec.ts +195 -0
  32. package/src/query/queryNumberOfSequencesOverTime.ts +33 -0
  33. package/src/query/queryPrevalenceOverTime.ts +10 -86
  34. package/src/utils/sort.ts +9 -0
  35. package/src/utils/temporalTestHelpers.ts +9 -0
  36. package/src/utils/utils.ts +7 -0
  37. package/src/web-components/input/gs-mutation-filter.stories.ts +57 -1
  38. package/src/web-components/visualization/gs-number-sequences-over-time.stories.ts +232 -0
  39. package/src/web-components/visualization/gs-number-sequences-over-time.tsx +140 -0
  40. package/src/web-components/visualization/index.ts +1 -0
@@ -0,0 +1,506 @@
1
+ {
2
+ "data": [
3
+ {
4
+ "count": 1,
5
+ "date": "2022-03-09"
6
+ },
7
+ {
8
+ "count": 1,
9
+ "date": "2022-09-13"
10
+ },
11
+ {
12
+ "count": 2,
13
+ "date": "2022-09-22"
14
+ },
15
+ {
16
+ "count": 1,
17
+ "date": "2022-09-11"
18
+ },
19
+ {
20
+ "count": 21,
21
+ "date": "2022-11-04"
22
+ },
23
+ {
24
+ "count": 119,
25
+ "date": "2022-12-01"
26
+ },
27
+ {
28
+ "count": 23,
29
+ "date": "2022-10-31"
30
+ },
31
+ {
32
+ "count": 9,
33
+ "date": "2022-10-27"
34
+ },
35
+ {
36
+ "count": 1,
37
+ "date": "2022-01-23"
38
+ },
39
+ {
40
+ "count": 58,
41
+ "date": "2022-11-18"
42
+ },
43
+ {
44
+ "count": 20,
45
+ "date": "2022-10-25"
46
+ },
47
+ {
48
+ "count": 16,
49
+ "date": "2022-10-19"
50
+ },
51
+ {
52
+ "count": 1,
53
+ "date": "2022-09-15"
54
+ },
55
+ {
56
+ "count": 19,
57
+ "date": "2022-11-06"
58
+ },
59
+ {
60
+ "count": 1,
61
+ "date": "2022-06-28"
62
+ },
63
+ {
64
+ "count": 8,
65
+ "date": "2022-10-18"
66
+ },
67
+ {
68
+ "count": 202,
69
+ "date": "2022-12-05"
70
+ },
71
+ {
72
+ "count": 38,
73
+ "date": "2022-11-01"
74
+ },
75
+ {
76
+ "count": 12,
77
+ "date": "2022-10-23"
78
+ },
79
+ {
80
+ "count": 8,
81
+ "date": "2022-10-15"
82
+ },
83
+ {
84
+ "count": 76,
85
+ "date": "2022-11-26"
86
+ },
87
+ {
88
+ "count": 10,
89
+ "date": "2022-10-14"
90
+ },
91
+ {
92
+ "count": 8,
93
+ "date": "2022-10-22"
94
+ },
95
+ {
96
+ "count": 4,
97
+ "date": "2022-09-29"
98
+ },
99
+ {
100
+ "count": 1,
101
+ "date": "2022-06-26"
102
+ },
103
+ {
104
+ "count": 5,
105
+ "date": "2022-10-12"
106
+ },
107
+ {
108
+ "count": 1,
109
+ "date": "2022-08-12"
110
+ },
111
+ {
112
+ "count": 1,
113
+ "date": "2022-09-14"
114
+ },
115
+ {
116
+ "count": 9,
117
+ "date": "2022-10-17"
118
+ },
119
+ {
120
+ "count": 3,
121
+ "date": "2022-09-30"
122
+ },
123
+ {
124
+ "count": 1,
125
+ "date": "2022-09-23"
126
+ },
127
+ {
128
+ "count": 1,
129
+ "date": "2022-02-23"
130
+ },
131
+ {
132
+ "count": 2,
133
+ "date": "2022-02-17"
134
+ },
135
+ {
136
+ "count": 86,
137
+ "date": "2022-12-03"
138
+ },
139
+ {
140
+ "count": 1,
141
+ "date": "2022-02-13"
142
+ },
143
+ {
144
+ "count": 1,
145
+ "date": "2022-01-28"
146
+ },
147
+ {
148
+ "count": 1,
149
+ "date": "2022-08-24"
150
+ },
151
+ {
152
+ "count": 15,
153
+ "date": "2022-10-29"
154
+ },
155
+ {
156
+ "count": 1,
157
+ "date": "2022-01-25"
158
+ },
159
+ {
160
+ "count": 1,
161
+ "date": "2022-02-22"
162
+ },
163
+ {
164
+ "count": 2,
165
+ "date": "2022-09-21"
166
+ },
167
+ {
168
+ "count": 163,
169
+ "date": "2022-12-02"
170
+ },
171
+ {
172
+ "count": 6,
173
+ "date": "2022-10-11"
174
+ },
175
+ {
176
+ "count": 7,
177
+ "date": "2022-10-10"
178
+ },
179
+ {
180
+ "count": 2,
181
+ "date": "2022-09-20"
182
+ },
183
+ {
184
+ "count": 21,
185
+ "date": "2022-10-26"
186
+ },
187
+ {
188
+ "count": 7,
189
+ "date": "2022-10-21"
190
+ },
191
+ {
192
+ "count": 5,
193
+ "date": "2022-10-05"
194
+ },
195
+ {
196
+ "count": 14,
197
+ "date": "2022-10-30"
198
+ },
199
+ {
200
+ "count": 223,
201
+ "date": "2022-12-16"
202
+ },
203
+ {
204
+ "count": 33,
205
+ "date": "2022-11-10"
206
+ },
207
+ {
208
+ "count": 149,
209
+ "date": "2022-12-11"
210
+ },
211
+ {
212
+ "count": 135,
213
+ "date": "2022-12-10"
214
+ },
215
+ {
216
+ "count": 16,
217
+ "date": "2022-10-28"
218
+ },
219
+ {
220
+ "count": 201,
221
+ "date": "2022-12-20"
222
+ },
223
+ {
224
+ "count": 131,
225
+ "date": "2022-12-14"
226
+ },
227
+ {
228
+ "count": 1,
229
+ "date": "2022-08-23"
230
+ },
231
+ {
232
+ "count": 252,
233
+ "date": "2022-12-12"
234
+ },
235
+ {
236
+ "count": 340,
237
+ "date": "2022-12-27"
238
+ },
239
+ {
240
+ "count": 118,
241
+ "date": "2022-12-08"
242
+ },
243
+ {
244
+ "count": 268,
245
+ "date": "2022-12-31"
246
+ },
247
+ {
248
+ "count": 148,
249
+ "date": "2022-11-29"
250
+ },
251
+ {
252
+ "count": 244,
253
+ "date": "2022-12-23"
254
+ },
255
+ {
256
+ "count": 131,
257
+ "date": "2022-12-07"
258
+ },
259
+ {
260
+ "count": 316,
261
+ "date": "2022-12-19"
262
+ },
263
+ {
264
+ "count": 3,
265
+ "date": "2022-10-16"
266
+ },
267
+ {
268
+ "count": 2,
269
+ "date": "2022-10-06"
270
+ },
271
+ {
272
+ "count": 130,
273
+ "date": "2022-12-13"
274
+ },
275
+ {
276
+ "count": 119,
277
+ "date": "2022-11-30"
278
+ },
279
+ {
280
+ "count": 6,
281
+ "date": "2022-10-02"
282
+ },
283
+ {
284
+ "count": 51,
285
+ "date": "2022-11-03"
286
+ },
287
+ {
288
+ "count": 23,
289
+ "date": "2022-11-02"
290
+ },
291
+ {
292
+ "count": 331,
293
+ "date": "2022-12-30"
294
+ },
295
+ {
296
+ "count": 151,
297
+ "date": "2022-12-06"
298
+ },
299
+ {
300
+ "count": 185,
301
+ "date": "2022-12-22"
302
+ },
303
+ {
304
+ "count": 24,
305
+ "date": "2022-11-24"
306
+ },
307
+ {
308
+ "count": 153,
309
+ "date": "2022-12-18"
310
+ },
311
+ {
312
+ "count": 37,
313
+ "date": "2022-11-11"
314
+ },
315
+ {
316
+ "count": 1,
317
+ "date": "2022-02-21"
318
+ },
319
+ {
320
+ "count": 337,
321
+ "date": "2022-12-29"
322
+ },
323
+ {
324
+ "count": 6,
325
+ "date": "2022-10-13"
326
+ },
327
+ {
328
+ "count": 4,
329
+ "date": "2022-09-26"
330
+ },
331
+ {
332
+ "count": 36,
333
+ "date": "2022-11-08"
334
+ },
335
+ {
336
+ "count": 41,
337
+ "date": "2022-11-12"
338
+ },
339
+ {
340
+ "count": 164,
341
+ "date": "2022-12-15"
342
+ },
343
+ {
344
+ "count": 172,
345
+ "date": "2022-12-09"
346
+ },
347
+ {
348
+ "count": 76,
349
+ "date": "2022-12-25"
350
+ },
351
+ {
352
+ "count": 177,
353
+ "date": "2022-12-17"
354
+ },
355
+ {
356
+ "count": 19,
357
+ "date": "2022-10-24"
358
+ },
359
+ {
360
+ "count": 137,
361
+ "date": "2022-11-27"
362
+ },
363
+ {
364
+ "count": 124,
365
+ "date": "2022-12-24"
366
+ },
367
+ {
368
+ "count": 69,
369
+ "date": "2022-11-17"
370
+ },
371
+ {
372
+ "count": 201,
373
+ "date": "2022-12-21"
374
+ },
375
+ {
376
+ "count": 99,
377
+ "date": "2022-12-04"
378
+ },
379
+ {
380
+ "count": 64,
381
+ "date": "2022-11-21"
382
+ },
383
+ {
384
+ "count": 333,
385
+ "date": "2022-12-26"
386
+ },
387
+ {
388
+ "count": 1,
389
+ "date": "2022-09-02"
390
+ },
391
+ {
392
+ "count": 69,
393
+ "date": "2022-11-23"
394
+ },
395
+ {
396
+ "count": 76,
397
+ "date": "2022-11-25"
398
+ },
399
+ {
400
+ "count": 67,
401
+ "date": "2022-11-22"
402
+ },
403
+ {
404
+ "count": 177,
405
+ "date": "2022-11-28"
406
+ },
407
+ {
408
+ "count": 29,
409
+ "date": "2022-11-20"
410
+ },
411
+ {
412
+ "count": 47,
413
+ "date": "2022-11-19"
414
+ },
415
+ {
416
+ "count": 1,
417
+ "date": "2022-09-06"
418
+ },
419
+ {
420
+ "count": 47,
421
+ "date": "2022-11-16"
422
+ },
423
+ {
424
+ "count": 1,
425
+ "date": "2022-09-24"
426
+ },
427
+ {
428
+ "count": 57,
429
+ "date": "2022-11-15"
430
+ },
431
+ {
432
+ "count": 40,
433
+ "date": "2022-11-13"
434
+ },
435
+ {
436
+ "count": 38,
437
+ "date": "2022-11-09"
438
+ },
439
+ {
440
+ "count": 76,
441
+ "date": "2022-11-14"
442
+ },
443
+ {
444
+ "count": 372,
445
+ "date": "2022-12-28"
446
+ },
447
+ {
448
+ "count": 28,
449
+ "date": "2022-11-07"
450
+ },
451
+ {
452
+ "count": 5,
453
+ "date": "2022-10-04"
454
+ },
455
+ {
456
+ "count": 1,
457
+ "date": "2022-08-27"
458
+ },
459
+ {
460
+ "count": 6,
461
+ "date": "2022-10-07"
462
+ },
463
+ {
464
+ "count": 21,
465
+ "date": "2022-11-05"
466
+ },
467
+ {
468
+ "count": 7,
469
+ "date": "2022-10-03"
470
+ },
471
+ {
472
+ "count": 12,
473
+ "date": "2022-10-20"
474
+ },
475
+ {
476
+ "count": 1,
477
+ "date": "2022-06-25"
478
+ },
479
+ {
480
+ "count": 3,
481
+ "date": "2022-10-01"
482
+ },
483
+ {
484
+ "count": 5,
485
+ "date": "2022-10-09"
486
+ },
487
+ {
488
+ "count": 3,
489
+ "date": "2022-10-08"
490
+ },
491
+ {
492
+ "count": 6,
493
+ "date": "2022-09-28"
494
+ },
495
+ {
496
+ "count": 1,
497
+ "date": "2022-09-25"
498
+ }
499
+ ],
500
+ "info": {
501
+ "dataVersion": "1720033519",
502
+ "requestId": "3d5507b7-d837-4c6e-9bf3-00b5b21286fd",
503
+ "requestInfo": "sars_cov-2_nextstrain_open on lapis.cov-spectrum.org at 2024-07-12T07:51:08.584671532",
504
+ "reportTo": "Please report to https://github.com/GenSpectrum/LAPIS/issues in case you encounter any unexpected issues. Please include the request ID and the requestInfo in your report."
505
+ }
506
+ }
@@ -0,0 +1,75 @@
1
+ import { describe, expect, test } from 'vitest';
2
+
3
+ import { getNumberOfSequencesOverTimeTableData } from './getNumberOfSequencesOverTimeTableData';
4
+ import { yearMonth } from '../../utils/temporalTestHelpers';
5
+
6
+ describe('getNumberOfSequencesOverTimeTableData', () => {
7
+ test('should return empty array if no data', () => {
8
+ const result = getNumberOfSequencesOverTimeTableData([], 'day');
9
+
10
+ expect(result).to.deep.equal([]);
11
+ });
12
+
13
+ test('should generate missing date ranges for non-overlapping datasets', () => {
14
+ const data = [
15
+ {
16
+ displayName: 'dataset1',
17
+ content: [{ count: 1, dateRange: yearMonth('2023-01') }],
18
+ },
19
+ {
20
+ displayName: 'dataset2',
21
+ content: [{ count: 3, dateRange: yearMonth('2023-04') }],
22
+ },
23
+ ];
24
+
25
+ const result = getNumberOfSequencesOverTimeTableData(data, 'month');
26
+
27
+ expect(result).to.deep.equal([
28
+ {
29
+ dataset1: 1,
30
+ dataset2: 0,
31
+ month: '2023-01',
32
+ },
33
+ {
34
+ dataset1: 0,
35
+ dataset2: 0,
36
+ month: '2023-02',
37
+ },
38
+ {
39
+ dataset1: 0,
40
+ dataset2: 0,
41
+ month: '2023-03',
42
+ },
43
+ {
44
+ dataset1: 0,
45
+ dataset2: 3,
46
+ month: '2023-04',
47
+ },
48
+ ]);
49
+ });
50
+
51
+ test('should maps null date ranges to "unknown"', () => {
52
+ const data = [
53
+ {
54
+ displayName: 'dataset1',
55
+ content: [
56
+ { count: 5, dateRange: null },
57
+ { count: 4, dateRange: yearMonth('2023-04') },
58
+ ],
59
+ },
60
+ ];
61
+
62
+ const result = getNumberOfSequencesOverTimeTableData(data, 'month');
63
+
64
+ expect(result).to.deep.equal([
65
+ {
66
+ dataset1: 5,
67
+ month: 'Unknown',
68
+ },
69
+ {
70
+ dataset1: 4,
71
+ month: '2023-04',
72
+ },
73
+ ]);
74
+ });
75
+ });
@@ -0,0 +1,39 @@
1
+ import type { NumberOfSequencesDatasets } from '../../query/queryNumberOfSequencesOverTime';
2
+ import { generateAllInRange, getMinMaxTemporal, type Temporal } from '../../utils/temporal';
3
+
4
+ type TableRow<DateRangeKey extends string> = { [K in DateRangeKey]: string } & { [key: string]: number };
5
+
6
+ export const getNumberOfSequencesOverTimeTableData = <DateRangeKey extends string>(
7
+ data: NumberOfSequencesDatasets,
8
+ dateRangeKey: DateRangeKey,
9
+ ) => {
10
+ const datasetsWithCountByDate = data.map(({ displayName, content }) => ({
11
+ displayName,
12
+ content: new Map(content.map((datum) => [datum.dateRange?.toString(), datum])),
13
+ }));
14
+
15
+ const allDateRangesThatOccurInData = datasetsWithCountByDate
16
+ .map(({ content }) => [...content.values()].map((datum) => datum.dateRange))
17
+ .reduce((acc, keys) => new Set([...acc, ...keys]), new Set<Temporal | null>());
18
+
19
+ const minMax = getMinMaxTemporal(allDateRangesThatOccurInData);
20
+ if (minMax === null) {
21
+ return [];
22
+ }
23
+
24
+ const allDateRanges: (Temporal | null)[] = generateAllInRange(...minMax);
25
+
26
+ if (allDateRangesThatOccurInData.has(null)) {
27
+ allDateRanges.unshift(null);
28
+ }
29
+
30
+ return allDateRanges.map((dateRange) => {
31
+ return datasetsWithCountByDate.reduce(
32
+ (acc, dataset) => ({
33
+ ...acc,
34
+ [dataset.displayName]: dataset.content.get(dateRange?.toString())?.count ?? 0,
35
+ }),
36
+ { [dateRangeKey]: dateRange?.toString() ?? 'Unknown' } as TableRow<DateRangeKey>,
37
+ );
38
+ });
39
+ };
@@ -0,0 +1,58 @@
1
+ import { Chart, type ChartConfiguration, type ChartDataset, registerables } from 'chart.js';
2
+ import { useMemo } from 'preact/hooks';
3
+
4
+ import { getNumberOfSequencesOverTimeTableData } from './getNumberOfSequencesOverTimeTableData';
5
+ import { type NumberOfSequencesDatasets } from '../../query/queryNumberOfSequencesOverTime';
6
+ import GsChart from '../components/chart';
7
+ import { singleGraphColorRGBAById } from '../shared/charts/colors';
8
+
9
+ interface NumberSequencesOverBarChartProps {
10
+ data: NumberOfSequencesDatasets;
11
+ }
12
+
13
+ Chart.register(...registerables);
14
+
15
+ export const NumberSequencesOverTimeBarChart = ({ data }: NumberSequencesOverBarChartProps) => {
16
+ const config: ChartConfiguration = useMemo(
17
+ () => ({
18
+ type: 'bar',
19
+ data: {
20
+ datasets: getDatasets(data),
21
+ },
22
+ options: {
23
+ maintainAspectRatio: false,
24
+ animation: false,
25
+ plugins: {
26
+ legend: {
27
+ display: false,
28
+ },
29
+ tooltip: {
30
+ mode: 'index',
31
+ intersect: false,
32
+ },
33
+ },
34
+ },
35
+ }),
36
+ [data],
37
+ );
38
+
39
+ return <GsChart configuration={config} />;
40
+ };
41
+
42
+ const getDatasets = (data: NumberOfSequencesDatasets) => {
43
+ const tableData = getNumberOfSequencesOverTimeTableData(data, 'date');
44
+
45
+ return data.map(
46
+ ({ displayName }, index) =>
47
+ ({
48
+ borderWidth: 1,
49
+ label: displayName,
50
+ backgroundColor: singleGraphColorRGBAById(index, 0.3),
51
+ borderColor: singleGraphColorRGBAById(index),
52
+ data: tableData.map((row) => ({
53
+ x: row.date,
54
+ y: row[displayName],
55
+ })),
56
+ }) as ChartDataset<'bar', { x: string; y: number }[]>,
57
+ );
58
+ };
@@ -0,0 +1,32 @@
1
+ import { useMemo } from 'preact/hooks';
2
+
3
+ import { getNumberOfSequencesOverTimeTableData } from './getNumberOfSequencesOverTimeTableData';
4
+ import { type NumberOfSequencesDatasets } from '../../query/queryNumberOfSequencesOverTime';
5
+ import { type TemporalGranularity } from '../../types';
6
+ import { Table } from '../components/table';
7
+
8
+ interface NumberSequencesOverTimeTableProps {
9
+ data: NumberOfSequencesDatasets;
10
+ granularity: TemporalGranularity;
11
+ pageSize: boolean | number;
12
+ }
13
+
14
+ export const NumberSequencesOverTimeTable = ({ data, granularity, pageSize }: NumberSequencesOverTimeTableProps) => {
15
+ const columns = [
16
+ {
17
+ name: granularity,
18
+ sort: true,
19
+ },
20
+ ...data.map((dataset) => ({
21
+ name: dataset.displayName,
22
+ sort: true,
23
+ })),
24
+ ];
25
+
26
+ const flatTableData = useMemo(() => {
27
+ const tableData = getNumberOfSequencesOverTimeTableData(data, granularity);
28
+ return Object.values(tableData).map((row) => Object.values(row));
29
+ }, [data, granularity]);
30
+
31
+ return <Table data={flatTableData} columns={columns} pageSize={pageSize} />;
32
+ };