@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.
- package/README.md +0 -7
- package/custom-elements.json +6 -25
- package/dist/components.d.ts +30 -36
- package/dist/components.js +943 -757
- package/dist/components.js.map +1 -1
- package/dist/util.d.ts +46 -30
- package/package.json +1 -5
- package/src/lapisApi/lapisApi.ts +21 -1
- package/src/lapisApi/lapisTypes.ts +36 -0
- package/src/preact/components/annotated-mutation.tsx +2 -2
- package/src/preact/{mutationsOverTime/mutations-over-time-grid.tsx → components/features-over-time-grid.tsx} +45 -52
- package/src/preact/genomeViewer/genome-data-viewer.tsx +2 -2
- package/src/preact/mutationsOverTime/MutationOverTimeData.ts +6 -4
- package/src/preact/mutationsOverTime/__mockData__/aminoAcidMutationsByDay/aminoAcidMutations.json +5482 -0
- package/src/preact/mutationsOverTime/__mockData__/aminoAcidMutationsByDay/aminoAcidMutationsOverTime.json +5496 -0
- package/src/preact/mutationsOverTime/__mockData__/byWeek/mutationsOverTime.json +7100 -0
- package/src/preact/mutationsOverTime/__mockData__/byWeek/nucleotideMutations.json +10122 -0
- package/src/preact/mutationsOverTime/__mockData__/defaultMockData/mutationsOverTime.json +12646 -0
- package/src/preact/mutationsOverTime/__mockData__/defaultMockData/nucleotideMutations.json +12632 -0
- package/src/preact/mutationsOverTime/__mockData__/request1800s/mutationsOverTime.json +16 -0
- package/src/preact/mutationsOverTime/__mockData__/request1800s/nucleotideMutations.json +11 -0
- package/src/preact/mutationsOverTime/__mockData__/withDisplayMutations/mutationsOverTime.json +52 -0
- package/src/preact/mutationsOverTime/getFilteredMutationsOverTime.spec.ts +3 -3
- package/src/preact/mutationsOverTime/mutations-over-time-grid-tooltip.tsx +3 -6
- package/src/preact/mutationsOverTime/mutations-over-time.stories.tsx +199 -12
- package/src/preact/mutationsOverTime/mutations-over-time.tsx +30 -35
- package/src/preact/wastewater/mutationsOverTime/wastewater-mutations-over-time.tsx +30 -3
- package/src/query/queryDatesInDataset.ts +89 -0
- package/src/query/queryMutationsOverTime.spec.ts +526 -548
- package/src/query/queryMutationsOverTime.ts +21 -232
- package/src/query/queryQueriesOverTime.spec.ts +432 -0
- package/src/query/queryQueriesOverTime.ts +125 -0
- package/src/utilEntrypoint.ts +3 -1
- package/src/utils/mutations.spec.ts +6 -0
- package/src/utils/mutations.ts +1 -1
- package/src/utils/temporalClass.ts +4 -0
- package/src/web-components/visualization/gs-mutations-over-time.spec-d.ts +0 -3
- package/src/web-components/visualization/gs-mutations-over-time.stories.ts +283 -17
- package/src/web-components/visualization/gs-mutations-over-time.tsx +0 -9
- package/standalone-bundle/dashboard-components.js +8935 -8781
- package/standalone-bundle/dashboard-components.js.map +1 -1
- package/dist/assets/mutationOverTimeWorker-f8Kp0S6V.js.map +0 -1
- package/src/preact/mutationsOverTime/__mockData__/aminoAcidMutationsByDay.ts +0 -47170
- package/src/preact/mutationsOverTime/__mockData__/byWeek.ts +0 -54026
- package/src/preact/mutationsOverTime/__mockData__/defaultMockData.ts +0 -108385
- package/src/preact/mutationsOverTime/__mockData__/mockConversion.ts +0 -54
- package/src/preact/mutationsOverTime/__mockData__/noDataWhenNoMutationsAreInFilter.ts +0 -23
- package/src/preact/mutationsOverTime/__mockData__/noDataWhenThereAreNoDatesInFilter.ts +0 -23
- package/src/preact/mutationsOverTime/__mockData__/showsMessageWhenTooManyMutations.ts +0 -65527
- package/src/preact/mutationsOverTime/__mockData__/withDisplayMutations.ts +0 -352
- package/src/preact/mutationsOverTime/__mockData__/withGaps.ts +0 -298
- package/src/preact/mutationsOverTime/mutationOverTimeWorker.mock.ts +0 -33
- package/src/preact/mutationsOverTime/mutationOverTimeWorker.ts +0 -29
- package/src/preact/webWorkers/useWebWorker.ts +0 -74
- package/src/preact/webWorkers/workerFunction.ts +0 -30
- package/src/query/queryMutationsOverTimeNewEndpoint.spec.ts +0 -988
- package/standalone-bundle/assets/mutationOverTimeWorker-AhhjjklP.js.map +0 -1
|
@@ -1,48 +1,20 @@
|
|
|
1
|
-
import {
|
|
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
|
-
|
|
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
|
|
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:
|
|
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
|
|
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
|
|
174
|
-
lapisFilter: LapisFilter
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
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:
|
|
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,
|
|
214
|
+
const mutationOverTimeData: Map2DContents<Substitution | Deletion, Temporal, ProportionValue> = {
|
|
299
215
|
keysFirstAxis: new Map(responseMutations.map((mutation) => [mutation.code, mutation])),
|
|
300
|
-
keysSecondAxis: new Map(
|
|
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
|
-
|
|
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
|
-
}
|