@genspectrum/dashboard-components 1.2.0 → 1.3.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/custom-elements.json +20 -1
- package/dist/assets/mutationOverTimeWorker-C7saVShx.js.map +1 -0
- package/dist/components.d.ts +20 -14
- package/dist/components.js +46 -8
- package/dist/components.js.map +1 -1
- package/dist/util.d.ts +14 -14
- package/package.json +1 -1
- package/src/lapisApi/lapisApi.ts +29 -0
- package/src/lapisApi/lapisTypes.ts +35 -1
- package/src/preact/mutationsOverTime/__mockData__/aminoAcidMutationsByDay.ts +1 -0
- package/src/preact/mutationsOverTime/__mockData__/byWeek.ts +1 -0
- package/src/preact/mutationsOverTime/__mockData__/defaultMockData.ts +1 -0
- package/src/preact/mutationsOverTime/__mockData__/noDataWhenNoMutationsAreInFilter.ts +1 -0
- package/src/preact/mutationsOverTime/__mockData__/noDataWhenThereAreNoDatesInFilter.ts +1 -0
- package/src/preact/mutationsOverTime/__mockData__/showsMessageWhenTooManyMutations.ts +1 -0
- package/src/preact/mutationsOverTime/mutations-over-time.stories.tsx +2 -0
- package/src/preact/mutationsOverTime/mutations-over-time.tsx +9 -3
- package/src/query/queryMutationsOverTime.ts +101 -23
- package/src/query/queryMutationsOverTimeNewEndpoint.spec.ts +935 -0
- package/src/web-components/visualization/gs-mutations-over-time.spec-d.ts +3 -0
- package/src/web-components/visualization/gs-mutations-over-time.stories.ts +3 -0
- package/src/web-components/visualization/gs-mutations-over-time.tsx +9 -0
- package/standalone-bundle/assets/mutationOverTimeWorker-DRRi3aMG.js.map +1 -0
- package/standalone-bundle/dashboard-components.js +3619 -3583
- package/standalone-bundle/dashboard-components.js.map +1 -1
- package/dist/assets/mutationOverTimeWorker-DpW4YOGl.js.map +0 -1
- package/standalone-bundle/assets/mutationOverTimeWorker-CZVvQBze.js.map +0 -1
package/dist/util.d.ts
CHANGED
|
@@ -917,7 +917,7 @@ declare global {
|
|
|
917
917
|
|
|
918
918
|
declare global {
|
|
919
919
|
interface HTMLElementTagNameMap {
|
|
920
|
-
'gs-
|
|
920
|
+
'gs-genome-data-viewer': GenomeDataViewerComponent;
|
|
921
921
|
}
|
|
922
922
|
}
|
|
923
923
|
|
|
@@ -925,7 +925,7 @@ declare global {
|
|
|
925
925
|
declare global {
|
|
926
926
|
namespace JSX {
|
|
927
927
|
interface IntrinsicElements {
|
|
928
|
-
'gs-
|
|
928
|
+
'gs-genome-data-viewer': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
|
|
929
929
|
}
|
|
930
930
|
}
|
|
931
931
|
}
|
|
@@ -933,7 +933,7 @@ declare global {
|
|
|
933
933
|
|
|
934
934
|
declare global {
|
|
935
935
|
interface HTMLElementTagNameMap {
|
|
936
|
-
'gs-
|
|
936
|
+
'gs-mutation-comparison-component': MutationComparisonComponent;
|
|
937
937
|
}
|
|
938
938
|
}
|
|
939
939
|
|
|
@@ -941,7 +941,7 @@ declare global {
|
|
|
941
941
|
declare global {
|
|
942
942
|
namespace JSX {
|
|
943
943
|
interface IntrinsicElements {
|
|
944
|
-
'gs-
|
|
944
|
+
'gs-mutation-comparison-component': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
|
|
945
945
|
}
|
|
946
946
|
}
|
|
947
947
|
}
|
|
@@ -981,7 +981,7 @@ declare global {
|
|
|
981
981
|
|
|
982
982
|
declare global {
|
|
983
983
|
interface HTMLElementTagNameMap {
|
|
984
|
-
'gs-
|
|
984
|
+
'gs-aggregate': AggregateComponent;
|
|
985
985
|
}
|
|
986
986
|
}
|
|
987
987
|
|
|
@@ -989,7 +989,7 @@ declare global {
|
|
|
989
989
|
declare global {
|
|
990
990
|
namespace JSX {
|
|
991
991
|
interface IntrinsicElements {
|
|
992
|
-
'gs-
|
|
992
|
+
'gs-aggregate': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
|
|
993
993
|
}
|
|
994
994
|
}
|
|
995
995
|
}
|
|
@@ -997,7 +997,7 @@ declare global {
|
|
|
997
997
|
|
|
998
998
|
declare global {
|
|
999
999
|
interface HTMLElementTagNameMap {
|
|
1000
|
-
'gs-
|
|
1000
|
+
'gs-prevalence-over-time': PrevalenceOverTimeComponent;
|
|
1001
1001
|
}
|
|
1002
1002
|
}
|
|
1003
1003
|
|
|
@@ -1005,7 +1005,7 @@ declare global {
|
|
|
1005
1005
|
declare global {
|
|
1006
1006
|
namespace JSX {
|
|
1007
1007
|
interface IntrinsicElements {
|
|
1008
|
-
'gs-
|
|
1008
|
+
'gs-prevalence-over-time': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
|
|
1009
1009
|
}
|
|
1010
1010
|
}
|
|
1011
1011
|
}
|
|
@@ -1013,7 +1013,7 @@ declare global {
|
|
|
1013
1013
|
|
|
1014
1014
|
declare global {
|
|
1015
1015
|
interface HTMLElementTagNameMap {
|
|
1016
|
-
'gs-
|
|
1016
|
+
'gs-mutations-over-time': MutationsOverTimeComponent;
|
|
1017
1017
|
}
|
|
1018
1018
|
}
|
|
1019
1019
|
|
|
@@ -1021,7 +1021,7 @@ declare global {
|
|
|
1021
1021
|
declare global {
|
|
1022
1022
|
namespace JSX {
|
|
1023
1023
|
interface IntrinsicElements {
|
|
1024
|
-
'gs-
|
|
1024
|
+
'gs-mutations-over-time': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
|
|
1025
1025
|
}
|
|
1026
1026
|
}
|
|
1027
1027
|
}
|
|
@@ -1045,7 +1045,7 @@ declare global {
|
|
|
1045
1045
|
|
|
1046
1046
|
declare global {
|
|
1047
1047
|
interface HTMLElementTagNameMap {
|
|
1048
|
-
'gs-
|
|
1048
|
+
'gs-sequences-by-location': SequencesByLocationComponent;
|
|
1049
1049
|
}
|
|
1050
1050
|
}
|
|
1051
1051
|
|
|
@@ -1053,7 +1053,7 @@ declare global {
|
|
|
1053
1053
|
declare global {
|
|
1054
1054
|
namespace JSX {
|
|
1055
1055
|
interface IntrinsicElements {
|
|
1056
|
-
'gs-
|
|
1056
|
+
'gs-sequences-by-location': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
|
|
1057
1057
|
}
|
|
1058
1058
|
}
|
|
1059
1059
|
}
|
|
@@ -1061,7 +1061,7 @@ declare global {
|
|
|
1061
1061
|
|
|
1062
1062
|
declare global {
|
|
1063
1063
|
interface HTMLElementTagNameMap {
|
|
1064
|
-
'gs-
|
|
1064
|
+
'gs-wastewater-mutations-over-time': WastewaterMutationsOverTimeComponent;
|
|
1065
1065
|
}
|
|
1066
1066
|
}
|
|
1067
1067
|
|
|
@@ -1069,7 +1069,7 @@ declare global {
|
|
|
1069
1069
|
declare global {
|
|
1070
1070
|
namespace JSX {
|
|
1071
1071
|
interface IntrinsicElements {
|
|
1072
|
-
'gs-
|
|
1072
|
+
'gs-wastewater-mutations-over-time': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
|
|
1073
1073
|
}
|
|
1074
1074
|
}
|
|
1075
1075
|
}
|
package/package.json
CHANGED
package/src/lapisApi/lapisApi.ts
CHANGED
|
@@ -9,6 +9,8 @@ import {
|
|
|
9
9
|
mutationsResponse,
|
|
10
10
|
problemDetail,
|
|
11
11
|
type ProblemDetail,
|
|
12
|
+
type MutationsOverTimeRequest,
|
|
13
|
+
mutationsOverTimeResponse,
|
|
12
14
|
} from './lapisTypes';
|
|
13
15
|
import { type SequenceType } from '../types';
|
|
14
16
|
import { lineageDefinitionResponseSchema } from './LineageDefinition';
|
|
@@ -112,6 +114,28 @@ export async function fetchSubstitutionsOrDeletions(
|
|
|
112
114
|
return mutationsResponse.parse(await response.json());
|
|
113
115
|
}
|
|
114
116
|
|
|
117
|
+
export async function fetchMutationsOverTime(
|
|
118
|
+
lapisUrl: string,
|
|
119
|
+
body: MutationsOverTimeRequest,
|
|
120
|
+
sequenceType: SequenceType,
|
|
121
|
+
signal?: AbortSignal,
|
|
122
|
+
) {
|
|
123
|
+
const response = await callLapis(
|
|
124
|
+
mutationsOverTimeEndpoint(lapisUrl, sequenceType),
|
|
125
|
+
{
|
|
126
|
+
method: 'POST',
|
|
127
|
+
headers: {
|
|
128
|
+
'Content-Type': 'application/json',
|
|
129
|
+
},
|
|
130
|
+
body: JSON.stringify(body),
|
|
131
|
+
signal,
|
|
132
|
+
},
|
|
133
|
+
`${sequenceType} mutations over time`,
|
|
134
|
+
);
|
|
135
|
+
|
|
136
|
+
return mutationsOverTimeResponse.parse(await response.json());
|
|
137
|
+
}
|
|
138
|
+
|
|
115
139
|
export async function fetchReferenceGenome(lapisUrl: string, signal?: AbortSignal) {
|
|
116
140
|
const response = await callLapis(
|
|
117
141
|
referenceGenomeEndpoint(lapisUrl),
|
|
@@ -215,6 +239,11 @@ export const substitutionsOrDeletionsEndpoint = (lapisUrl: string, sequenceType:
|
|
|
215
239
|
? `${lapisUrl}/sample/aminoAcidMutations`
|
|
216
240
|
: `${lapisUrl}/sample/nucleotideMutations`;
|
|
217
241
|
};
|
|
242
|
+
export const mutationsOverTimeEndpoint = (lapisUrl: string, sequenceType: SequenceType) => {
|
|
243
|
+
return sequenceType === 'amino acid'
|
|
244
|
+
? `${lapisUrl}/component/aminoAcidMutationsOverTime`
|
|
245
|
+
: `${lapisUrl}/component/nucleotideMutationsOverTime`;
|
|
246
|
+
};
|
|
218
247
|
export const referenceGenomeEndpoint = (lapisUrl: string) => `${lapisUrl}/sample/referenceGenome`;
|
|
219
248
|
export const lineageDefinitionEndpoint = (lapisUrl: string, lapisField: string) =>
|
|
220
249
|
`${lapisUrl}/sample/lineageDefinition/${lapisField}`;
|
|
@@ -7,6 +7,13 @@ export const orderBy = z.object({
|
|
|
7
7
|
type: orderByType,
|
|
8
8
|
});
|
|
9
9
|
|
|
10
|
+
const filterValue = z.union([z.string(), z.number(), z.boolean(), z.null(), z.undefined(), z.array(z.string())]);
|
|
11
|
+
|
|
12
|
+
const dateRange = z.object({
|
|
13
|
+
dateFrom: z.string(),
|
|
14
|
+
dateTo: z.string(),
|
|
15
|
+
});
|
|
16
|
+
|
|
10
17
|
export const lapisBaseRequest = z
|
|
11
18
|
.object({
|
|
12
19
|
limit: z.number().optional(),
|
|
@@ -14,7 +21,7 @@ export const lapisBaseRequest = z
|
|
|
14
21
|
fields: z.array(z.string()).optional(),
|
|
15
22
|
orderBy: z.array(orderBy).optional(),
|
|
16
23
|
})
|
|
17
|
-
.catchall(
|
|
24
|
+
.catchall(filterValue);
|
|
18
25
|
export type LapisBaseRequest = z.infer<typeof lapisBaseRequest>;
|
|
19
26
|
|
|
20
27
|
export const mutationsRequest = lapisBaseRequest.extend({ minProportion: z.number().optional() });
|
|
@@ -32,6 +39,33 @@ const mutationProportionCount = z.object({
|
|
|
32
39
|
export const mutationsResponse = makeLapisResponse(z.array(mutationProportionCount));
|
|
33
40
|
export type MutationsResponse = z.infer<typeof mutationsResponse>;
|
|
34
41
|
|
|
42
|
+
export const mutationsOverTimeRequest = z.object({
|
|
43
|
+
filters: z.record(filterValue),
|
|
44
|
+
downloadAsFile: z.boolean().optional(),
|
|
45
|
+
downloadFileBasename: z.string().optional(),
|
|
46
|
+
compression: z.enum(['gzip', 'none']).optional(),
|
|
47
|
+
includeMutations: z.array(z.string()).optional(),
|
|
48
|
+
dateRanges: z.array(dateRange).optional(),
|
|
49
|
+
dateField: z.string().optional(),
|
|
50
|
+
});
|
|
51
|
+
export type MutationsOverTimeRequest = z.infer<typeof mutationsOverTimeRequest>;
|
|
52
|
+
|
|
53
|
+
export const mutationsOverTimeResponse = makeLapisResponse(
|
|
54
|
+
z.object({
|
|
55
|
+
mutations: z.array(z.string()),
|
|
56
|
+
dateRanges: z.array(dateRange),
|
|
57
|
+
data: z.array(
|
|
58
|
+
z.array(
|
|
59
|
+
z.object({
|
|
60
|
+
count: z.number(),
|
|
61
|
+
coverage: z.number(),
|
|
62
|
+
}),
|
|
63
|
+
),
|
|
64
|
+
),
|
|
65
|
+
}),
|
|
66
|
+
);
|
|
67
|
+
export type MutationsOverTimeResponse = z.infer<typeof mutationsOverTimeResponse>;
|
|
68
|
+
|
|
35
69
|
const insertionCount = z.object({
|
|
36
70
|
insertion: z.string(),
|
|
37
71
|
count: z.number(),
|
|
@@ -36,6 +36,7 @@ const meta: Meta<MutationsOverTimeProps> = {
|
|
|
36
36
|
displayMutations: { control: 'object' },
|
|
37
37
|
initialMeanProportionInterval: { control: 'object' },
|
|
38
38
|
pageSizes: { control: 'object' },
|
|
39
|
+
useNewEndpoint: { control: 'boolean' },
|
|
39
40
|
},
|
|
40
41
|
parameters: {
|
|
41
42
|
fetchMock: {},
|
|
@@ -80,6 +81,7 @@ export const Default: StoryObj<MutationsOverTimeProps> = {
|
|
|
80
81
|
granularity: 'month',
|
|
81
82
|
lapisDateField: 'date',
|
|
82
83
|
initialMeanProportionInterval: { min: 0.05, max: 0.9 },
|
|
84
|
+
useNewEndpoint: false,
|
|
83
85
|
pageSizes: [10, 20, 30, 40, 50],
|
|
84
86
|
},
|
|
85
87
|
};
|
|
@@ -12,6 +12,7 @@ import {
|
|
|
12
12
|
} from './getFilteredMutationsOverTimeData';
|
|
13
13
|
import { type MutationOverTimeWorkerResponse } from './mutationOverTimeWorker';
|
|
14
14
|
import MutationsOverTimeGrid from './mutations-over-time-grid';
|
|
15
|
+
import { type MutationOverTimeQuery } from '../../query/queryMutationsOverTime';
|
|
15
16
|
import {
|
|
16
17
|
lapisFilterSchema,
|
|
17
18
|
sequenceTypeSchema,
|
|
@@ -52,6 +53,7 @@ const mutationOverTimeSchema = z.object({
|
|
|
52
53
|
views: z.array(mutationsOverTimeViewSchema),
|
|
53
54
|
granularity: temporalGranularitySchema,
|
|
54
55
|
lapisDateField: z.string().min(1),
|
|
56
|
+
useNewEndpoint: z.boolean().optional(),
|
|
55
57
|
displayMutations: displayMutationsSchema.optional(),
|
|
56
58
|
initialMeanProportionInterval: z.object({
|
|
57
59
|
min: z.number().min(0).max(1),
|
|
@@ -76,19 +78,23 @@ export const MutationsOverTime: FunctionComponent<MutationsOverTimeProps> = (com
|
|
|
76
78
|
);
|
|
77
79
|
};
|
|
78
80
|
|
|
79
|
-
export const MutationsOverTimeInner: FunctionComponent<MutationsOverTimeProps> = (
|
|
81
|
+
export const MutationsOverTimeInner: FunctionComponent<MutationsOverTimeProps> = ({
|
|
82
|
+
useNewEndpoint = false,
|
|
83
|
+
...componentProps
|
|
84
|
+
}) => {
|
|
80
85
|
const lapis = useLapisUrl();
|
|
81
86
|
const { lapisFilter, sequenceType, granularity, lapisDateField } = componentProps;
|
|
82
87
|
|
|
83
|
-
const messageToWorker = useMemo(() => {
|
|
88
|
+
const messageToWorker: MutationOverTimeQuery = useMemo(() => {
|
|
84
89
|
return {
|
|
85
90
|
lapisFilter,
|
|
86
91
|
sequenceType,
|
|
87
92
|
granularity,
|
|
88
93
|
lapisDateField,
|
|
89
94
|
lapis,
|
|
95
|
+
useNewEndpoint,
|
|
90
96
|
};
|
|
91
|
-
}, [granularity, lapis, lapisDateField, lapisFilter, sequenceType]);
|
|
97
|
+
}, [granularity, lapis, lapisDateField, lapisFilter, sequenceType, useNewEndpoint]);
|
|
92
98
|
|
|
93
99
|
const { data, error, isLoading } = useWebWorker<MutationOverTimeWorkerResponse>(
|
|
94
100
|
messageToWorker,
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { mapDateToGranularityRange } from './queryAggregatedDataOverTime';
|
|
2
|
+
import { fetchMutationsOverTime } from '../lapisApi/lapisApi';
|
|
2
3
|
import { FetchAggregatedOperator } from '../operator/FetchAggregatedOperator';
|
|
3
4
|
import { FetchSubstitutionsOrDeletionsOperator } from '../operator/FetchSubstitutionsOrDeletionsOperator';
|
|
4
5
|
import { GroupByAndSumOperator } from '../operator/GroupByAndSumOperator';
|
|
@@ -16,6 +17,7 @@ import {
|
|
|
16
17
|
type SubstitutionOrDeletionEntry,
|
|
17
18
|
type TemporalGranularity,
|
|
18
19
|
} from '../types';
|
|
20
|
+
import { type Map2DContents } from '../utils/map2d';
|
|
19
21
|
import { type Deletion, type Substitution, toSubstitutionOrDeletion } from '../utils/mutations';
|
|
20
22
|
import {
|
|
21
23
|
compareTemporal,
|
|
@@ -92,17 +94,13 @@ export type MutationOverTimeQuery = {
|
|
|
92
94
|
lapis: string;
|
|
93
95
|
lapisDateField: string;
|
|
94
96
|
granularity: TemporalGranularity;
|
|
97
|
+
useNewEndpoint?: boolean;
|
|
95
98
|
signal?: AbortSignal;
|
|
96
99
|
};
|
|
97
100
|
|
|
98
|
-
export async function queryMutationsOverTimeData({
|
|
99
|
-
lapisFilter,
|
|
100
|
-
|
|
101
|
-
lapis,
|
|
102
|
-
lapisDateField,
|
|
103
|
-
granularity,
|
|
104
|
-
signal,
|
|
105
|
-
}: MutationOverTimeQuery) {
|
|
101
|
+
export async function queryMutationsOverTimeData(query: MutationOverTimeQuery) {
|
|
102
|
+
const { lapisFilter, sequenceType, lapis, lapisDateField, granularity, useNewEndpoint, signal } = query;
|
|
103
|
+
|
|
106
104
|
const requestedDateRanges = await getDatesInDataset(lapisFilter, lapis, granularity, lapisDateField, signal);
|
|
107
105
|
|
|
108
106
|
if (requestedDateRanges.length > MAX_NUMBER_OF_GRID_COLUMNS) {
|
|
@@ -114,7 +112,25 @@ export async function queryMutationsOverTimeData({
|
|
|
114
112
|
);
|
|
115
113
|
}
|
|
116
114
|
|
|
117
|
-
const
|
|
115
|
+
const overallMutationData = queryOverallMutationData({
|
|
116
|
+
lapisFilter,
|
|
117
|
+
sequenceType,
|
|
118
|
+
lapis,
|
|
119
|
+
lapisDateField,
|
|
120
|
+
granularity,
|
|
121
|
+
}).then((r) => r.content);
|
|
122
|
+
|
|
123
|
+
return useNewEndpoint === true
|
|
124
|
+
? queryMutationsOverTimeDataDirectEndpoint(requestedDateRanges, overallMutationData, query)
|
|
125
|
+
: queryMutationsOverTimeDataMultiQuery(requestedDateRanges, overallMutationData, query);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
async function queryMutationsOverTimeDataMultiQuery(
|
|
129
|
+
allDates: TemporalClass[],
|
|
130
|
+
overallMutationDataPromise: Promise<SubstitutionOrDeletionEntry[]>,
|
|
131
|
+
{ lapisFilter, sequenceType, lapis, lapisDateField, signal }: MutationOverTimeQuery,
|
|
132
|
+
) {
|
|
133
|
+
const subQueries = allDates.map(async (date) => {
|
|
118
134
|
const dateFrom = date.firstDay.toString();
|
|
119
135
|
const dateTo = date.lastDay.toString();
|
|
120
136
|
|
|
@@ -124,8 +140,10 @@ export async function queryMutationsOverTimeData({
|
|
|
124
140
|
[`${lapisDateField}To`]: dateTo,
|
|
125
141
|
};
|
|
126
142
|
|
|
127
|
-
const data = await
|
|
128
|
-
|
|
143
|
+
const [data, totalCountQuery] = await Promise.all([
|
|
144
|
+
fetchAndPrepareSubstitutionsOrDeletions(filter, sequenceType).evaluate(lapis, signal),
|
|
145
|
+
getTotalNumberOfSequencesInDateRange(filter).evaluate(lapis, signal),
|
|
146
|
+
]);
|
|
129
147
|
|
|
130
148
|
return {
|
|
131
149
|
date,
|
|
@@ -135,20 +153,80 @@ export async function queryMutationsOverTimeData({
|
|
|
135
153
|
});
|
|
136
154
|
|
|
137
155
|
const data = await Promise.all(subQueries);
|
|
156
|
+
const overallMutationData = await overallMutationDataPromise;
|
|
138
157
|
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
158
|
+
return {
|
|
159
|
+
mutationOverTimeData: groupByMutation(data, overallMutationData),
|
|
160
|
+
overallMutationData,
|
|
161
|
+
};
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
async function queryMutationsOverTimeDataDirectEndpoint(
|
|
165
|
+
allDates: TemporalClass[],
|
|
166
|
+
overallMutationDataPromise: Promise<SubstitutionOrDeletionEntry[]>,
|
|
167
|
+
{ lapisFilter, sequenceType, lapis, lapisDateField, signal }: MutationOverTimeQuery,
|
|
168
|
+
): Promise<{
|
|
169
|
+
mutationOverTimeData: BaseMutationOverTimeDataMap;
|
|
170
|
+
overallMutationData: SubstitutionOrDeletionEntry[];
|
|
171
|
+
}> {
|
|
172
|
+
const overallMutationData = await overallMutationDataPromise;
|
|
173
|
+
overallMutationData.sort((a, b) => sortSubstitutionsAndDeletions(a.mutation, b.mutation));
|
|
174
|
+
const totalCounts = await Promise.all(
|
|
175
|
+
allDates.map(async (date) => {
|
|
176
|
+
const filter = {
|
|
177
|
+
...lapisFilter,
|
|
178
|
+
[`${lapisDateField}From`]: date.firstDay.toString(),
|
|
179
|
+
[`${lapisDateField}To`]: date.lastDay.toString(),
|
|
180
|
+
};
|
|
181
|
+
|
|
182
|
+
const totalCountQuery = await getTotalNumberOfSequencesInDateRange(filter).evaluate(lapis, signal);
|
|
183
|
+
|
|
184
|
+
return totalCountQuery.content[0].count;
|
|
185
|
+
}),
|
|
186
|
+
);
|
|
187
|
+
|
|
188
|
+
const includeMutations = overallMutationData.map((value) => value.mutation.code);
|
|
189
|
+
const apiResult = await fetchMutationsOverTime(
|
|
190
|
+
lapis,
|
|
191
|
+
{
|
|
192
|
+
filters: lapisFilter,
|
|
193
|
+
dateRanges: allDates.map((date) => ({
|
|
194
|
+
dateFrom: date.firstDay.toString(),
|
|
195
|
+
dateTo: date.lastDay.toString(),
|
|
196
|
+
})),
|
|
197
|
+
includeMutations,
|
|
198
|
+
dateField: lapisDateField,
|
|
199
|
+
},
|
|
200
|
+
sequenceType,
|
|
201
|
+
signal,
|
|
202
|
+
);
|
|
203
|
+
|
|
204
|
+
const mutationOverTimeData: Map2DContents<Substitution | Deletion, Temporal, MutationOverTimeMutationValue> = {
|
|
205
|
+
keysFirstAxis: new Map(overallMutationData.map((value) => [value.mutation.code, value.mutation])),
|
|
206
|
+
keysSecondAxis: new Map(allDates.map((date) => [date.dateString, date])),
|
|
207
|
+
data: new Map(
|
|
208
|
+
overallMutationData.map((mutation, i) => [
|
|
209
|
+
mutation.mutation.code,
|
|
210
|
+
new Map(
|
|
211
|
+
allDates.map((date, j): [string, MutationOverTimeMutationValue] => [
|
|
212
|
+
date.dateString,
|
|
213
|
+
{
|
|
214
|
+
type: 'value',
|
|
215
|
+
// 'coverage' in the API resp. is the number of seqs. that have a non-ambiguous symbol at position
|
|
216
|
+
// 'count' in the API resp. is the number of seqs with the mutation
|
|
217
|
+
proportion: apiResult.data.data[i][j].count / apiResult.data.data[i][j].coverage,
|
|
218
|
+
count: apiResult.data.data[i][j].count,
|
|
219
|
+
totalCount: totalCounts[j],
|
|
220
|
+
},
|
|
221
|
+
]),
|
|
222
|
+
),
|
|
223
|
+
]),
|
|
224
|
+
),
|
|
225
|
+
};
|
|
148
226
|
|
|
149
227
|
return {
|
|
150
|
-
mutationOverTimeData:
|
|
151
|
-
overallMutationData
|
|
228
|
+
mutationOverTimeData: new BaseMutationOverTimeDataMap(mutationOverTimeData),
|
|
229
|
+
overallMutationData,
|
|
152
230
|
};
|
|
153
231
|
}
|
|
154
232
|
|
|
@@ -236,7 +314,7 @@ export function serializeTemporal(date: Temporal) {
|
|
|
236
314
|
export function groupByMutation(
|
|
237
315
|
data: MutationOverTimeData[],
|
|
238
316
|
overallMutationData: (SubstitutionEntry | DeletionEntry)[],
|
|
239
|
-
) {
|
|
317
|
+
): BaseMutationOverTimeDataMap {
|
|
240
318
|
const dataArray = new BaseMutationOverTimeDataMap();
|
|
241
319
|
|
|
242
320
|
const allDates = data.map((mutationData) => mutationData.date);
|