@genspectrum/dashboard-components 1.16.0 → 1.17.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 +3 -3
- package/dist/components.d.ts +4 -4
- package/dist/components.js +449 -246
- package/dist/components.js.map +1 -1
- package/dist/util.d.ts +6 -6
- package/package.json +1 -1
- package/src/preact/MutationAnnotationsContext.tsx +1 -1
- package/src/preact/components/csv-download-button.tsx +22 -14
- package/src/preact/components/features-over-time-grid.tsx +189 -43
- package/src/preact/components/mutations-over-time-mutations-filter.stories.tsx +1 -1
- package/src/preact/components/mutations-over-time-mutations-filter.tsx +1 -1
- package/src/preact/mutationsOverTime/__mockData__/aminoAcidMutationsByDay/aminoAcidMutationsOverTimePage1.json +52 -0
- package/src/preact/mutationsOverTime/__mockData__/byWeek/mutationsOverTimePage1.json +76 -0
- package/src/preact/mutationsOverTime/__mockData__/defaultMockData/mockDefaultMutationsOverTimeWithFilter.json +43 -0
- package/src/preact/mutationsOverTime/__mockData__/defaultMockData/mutationsOverTimePage1.json +126 -0
- package/src/preact/mutationsOverTime/__mockData__/defaultMockData/mutationsOverTimePage2.json +116 -0
- package/src/preact/mutationsOverTime/__mockData__/defaultMockData/mutationsOverTimePageSize20.json +216 -0
- package/src/preact/mutationsOverTime/getFilteredMutationCodes.spec.ts +236 -0
- package/src/preact/mutationsOverTime/{getFilteredMutationsOverTimeData.ts → getFilteredMutationCodes.ts} +29 -44
- package/src/preact/mutationsOverTime/mutations-over-time.stories.tsx +128 -23
- package/src/preact/mutationsOverTime/mutations-over-time.tsx +139 -74
- package/src/preact/mutationsOverTime/useMutationsOverTimePageData.ts +111 -0
- package/src/preact/shared/tanstackTable/pagination-context.tsx +5 -2
- package/src/preact/shared/tanstackTable/pagination.tsx +11 -9
- package/src/preact/shared/tanstackTable/tanstackTable.tsx +7 -4
- package/src/preact/wastewater/mutationsOverTime/wastewater-mutations-over-time.tsx +1 -1
- package/src/query/queryMutationsOverTime.spec.ts +187 -662
- package/src/query/queryMutationsOverTime.ts +46 -33
- package/src/utils/useControlledState.ts +15 -0
- package/src/web-components/visualization/gs-mutations-over-time.stories.ts +78 -22
- package/standalone-bundle/dashboard-components.js +6872 -6690
- package/standalone-bundle/dashboard-components.js.map +1 -1
- package/src/preact/mutationsOverTime/__mockData__/aminoAcidMutationsByDay/aminoAcidMutationsOverTime.json +0 -5496
- package/src/preact/mutationsOverTime/__mockData__/byWeek/mutationsOverTime.json +0 -7100
- package/src/preact/mutationsOverTime/__mockData__/defaultMockData/mutationsOverTime.json +0 -12646
- package/src/preact/mutationsOverTime/getFilteredMutationsOverTime.spec.ts +0 -417
|
@@ -1,417 +0,0 @@
|
|
|
1
|
-
import { describe, expect, it } from 'vitest';
|
|
2
|
-
|
|
3
|
-
import { BaseMutationOverTimeDataMap } from './MutationOverTimeData';
|
|
4
|
-
import { getFilteredMutationOverTimeData, type MutationFilter } from './getFilteredMutationsOverTimeData';
|
|
5
|
-
import { type ProportionValue } from '../../query/queryMutationsOverTime';
|
|
6
|
-
import { type DeletionEntry, type SubstitutionEntry } from '../../types';
|
|
7
|
-
import { type Deletion, type Substitution } from '../../utils/mutations';
|
|
8
|
-
import { type TemporalClass } from '../../utils/temporalClass';
|
|
9
|
-
import { yearMonthDay } from '../../utils/temporalTestHelpers';
|
|
10
|
-
import { type MutationAnnotations } from '../../web-components/mutation-annotations-context';
|
|
11
|
-
import { getMutationAnnotationsContext, getMutationAnnotationsProvider } from '../MutationAnnotationsContext';
|
|
12
|
-
|
|
13
|
-
describe('getFilteredMutationOverTimeData', () => {
|
|
14
|
-
it('should filter by displayed segments', () => {
|
|
15
|
-
const { data, overallMutationData } = prepareMutationOverTimeData([
|
|
16
|
-
someSubstitutionEntry,
|
|
17
|
-
anotherSubstitutionEntry,
|
|
18
|
-
someDeletionEntry,
|
|
19
|
-
]);
|
|
20
|
-
|
|
21
|
-
const result = getFilteredMutationOverTimeData({
|
|
22
|
-
data,
|
|
23
|
-
overallMutationData,
|
|
24
|
-
displayedSegments: [
|
|
25
|
-
{ segment: 'someSegment', checked: false, label: 'Some Segment' },
|
|
26
|
-
{ segment: 'someOtherSegment', checked: true, label: 'Some Other Segment' },
|
|
27
|
-
],
|
|
28
|
-
displayedMutationTypes: [],
|
|
29
|
-
proportionInterval,
|
|
30
|
-
hideGaps: false,
|
|
31
|
-
displayMutations: undefined,
|
|
32
|
-
mutationFilterValue: { textFilter: '', annotationNameFilter: new Set() },
|
|
33
|
-
sequenceType: 'nucleotide',
|
|
34
|
-
annotationProvider: () => {
|
|
35
|
-
return [];
|
|
36
|
-
},
|
|
37
|
-
});
|
|
38
|
-
|
|
39
|
-
expect(result.getFirstAxisKeys()).to.deep.equal([anotherSubstitution]);
|
|
40
|
-
});
|
|
41
|
-
|
|
42
|
-
it('should filter by mutation types', () => {
|
|
43
|
-
const { data, overallMutationData } = prepareMutationOverTimeData([
|
|
44
|
-
someSubstitutionEntry,
|
|
45
|
-
anotherSubstitutionEntry,
|
|
46
|
-
someDeletionEntry,
|
|
47
|
-
]);
|
|
48
|
-
|
|
49
|
-
const result = getFilteredMutationOverTimeData({
|
|
50
|
-
data,
|
|
51
|
-
overallMutationData,
|
|
52
|
-
displayedSegments: [],
|
|
53
|
-
displayedMutationTypes: [
|
|
54
|
-
{
|
|
55
|
-
type: 'substitution',
|
|
56
|
-
checked: false,
|
|
57
|
-
label: 'Substitution',
|
|
58
|
-
},
|
|
59
|
-
{
|
|
60
|
-
type: 'deletion',
|
|
61
|
-
checked: true,
|
|
62
|
-
label: 'Deletion',
|
|
63
|
-
},
|
|
64
|
-
],
|
|
65
|
-
proportionInterval,
|
|
66
|
-
hideGaps: false,
|
|
67
|
-
mutationFilterValue: { textFilter: '', annotationNameFilter: new Set() },
|
|
68
|
-
sequenceType: 'nucleotide',
|
|
69
|
-
annotationProvider: () => {
|
|
70
|
-
return [];
|
|
71
|
-
},
|
|
72
|
-
});
|
|
73
|
-
|
|
74
|
-
expect(result.getFirstAxisKeys()).to.deep.equal([someDeletion]);
|
|
75
|
-
});
|
|
76
|
-
|
|
77
|
-
it('should remove mutations where overall proportion is below filter', () => {
|
|
78
|
-
const { data, overallMutationData } = prepareMutationOverTimeData([
|
|
79
|
-
{ ...someSubstitutionEntry, proportion: belowFilter },
|
|
80
|
-
{ ...anotherSubstitutionEntry, proportion: inFilter },
|
|
81
|
-
{ ...someDeletionEntry, proportion: inFilter },
|
|
82
|
-
]);
|
|
83
|
-
|
|
84
|
-
const result = getFilteredMutationOverTimeData({
|
|
85
|
-
data,
|
|
86
|
-
overallMutationData,
|
|
87
|
-
displayedSegments: [],
|
|
88
|
-
displayedMutationTypes: [],
|
|
89
|
-
proportionInterval,
|
|
90
|
-
hideGaps: false,
|
|
91
|
-
mutationFilterValue: { textFilter: '', annotationNameFilter: new Set() },
|
|
92
|
-
sequenceType: 'nucleotide',
|
|
93
|
-
annotationProvider: () => {
|
|
94
|
-
return [];
|
|
95
|
-
},
|
|
96
|
-
});
|
|
97
|
-
|
|
98
|
-
expect(result.getFirstAxisKeys()).to.deep.equal([anotherSubstitution, someDeletion]);
|
|
99
|
-
});
|
|
100
|
-
|
|
101
|
-
it('should remove mutations where overall proportion is above filter', () => {
|
|
102
|
-
const { data, overallMutationData } = prepareMutationOverTimeData([
|
|
103
|
-
{ ...someSubstitutionEntry, proportion: aboveFilter },
|
|
104
|
-
{ ...anotherSubstitutionEntry, proportion: inFilter },
|
|
105
|
-
{ ...someDeletionEntry, proportion: inFilter },
|
|
106
|
-
]);
|
|
107
|
-
|
|
108
|
-
const result = getFilteredMutationOverTimeData({
|
|
109
|
-
data,
|
|
110
|
-
overallMutationData,
|
|
111
|
-
displayedSegments: [],
|
|
112
|
-
displayedMutationTypes: [],
|
|
113
|
-
proportionInterval,
|
|
114
|
-
hideGaps: false,
|
|
115
|
-
mutationFilterValue: { textFilter: '', annotationNameFilter: new Set() },
|
|
116
|
-
sequenceType: 'nucleotide',
|
|
117
|
-
annotationProvider: () => {
|
|
118
|
-
return [];
|
|
119
|
-
},
|
|
120
|
-
});
|
|
121
|
-
|
|
122
|
-
expect(result.getFirstAxisKeys()).to.deep.equal([anotherSubstitution, someDeletion]);
|
|
123
|
-
});
|
|
124
|
-
|
|
125
|
-
it('should not remove mutations where overall proportion is above filter but single proportion is below filter', () => {
|
|
126
|
-
const { data, overallMutationData } = prepareMutationOverTimeData([
|
|
127
|
-
someSubstitutionEntry,
|
|
128
|
-
anotherSubstitutionEntry,
|
|
129
|
-
someDeletionEntry,
|
|
130
|
-
]);
|
|
131
|
-
data.set(someSubstitution, someTemporal, { ...someMutationOverTimeValue, proportion: belowFilter });
|
|
132
|
-
|
|
133
|
-
const result = getFilteredMutationOverTimeData({
|
|
134
|
-
data,
|
|
135
|
-
overallMutationData,
|
|
136
|
-
displayedSegments: [],
|
|
137
|
-
displayedMutationTypes: [],
|
|
138
|
-
proportionInterval,
|
|
139
|
-
hideGaps: false,
|
|
140
|
-
mutationFilterValue: { textFilter: '', annotationNameFilter: new Set() },
|
|
141
|
-
sequenceType: 'nucleotide',
|
|
142
|
-
annotationProvider: () => {
|
|
143
|
-
return [];
|
|
144
|
-
},
|
|
145
|
-
});
|
|
146
|
-
|
|
147
|
-
expect(result.getFirstAxisKeys()).to.deep.equal([someSubstitution, anotherSubstitution, someDeletion]);
|
|
148
|
-
});
|
|
149
|
-
|
|
150
|
-
it('should not remove mutations where overall proportion is below max but single proportion is above max', () => {
|
|
151
|
-
const { data, overallMutationData } = prepareMutationOverTimeData([
|
|
152
|
-
someSubstitutionEntry,
|
|
153
|
-
anotherSubstitutionEntry,
|
|
154
|
-
someDeletionEntry,
|
|
155
|
-
]);
|
|
156
|
-
data.set(someSubstitution, someTemporal, { ...someMutationOverTimeValue, proportion: aboveFilter });
|
|
157
|
-
|
|
158
|
-
const result = getFilteredMutationOverTimeData({
|
|
159
|
-
data,
|
|
160
|
-
overallMutationData,
|
|
161
|
-
displayedSegments: [],
|
|
162
|
-
displayedMutationTypes: [],
|
|
163
|
-
proportionInterval,
|
|
164
|
-
hideGaps: false,
|
|
165
|
-
mutationFilterValue: { textFilter: '', annotationNameFilter: new Set() },
|
|
166
|
-
sequenceType: 'nucleotide',
|
|
167
|
-
annotationProvider: () => {
|
|
168
|
-
return [];
|
|
169
|
-
},
|
|
170
|
-
});
|
|
171
|
-
|
|
172
|
-
expect(result.getFirstAxisKeys()).to.deep.equal([someSubstitution, anotherSubstitution, someDeletion]);
|
|
173
|
-
});
|
|
174
|
-
|
|
175
|
-
it('should not remove mutations where overall proportion is at lower bound of filter', () => {
|
|
176
|
-
const { data, overallMutationData } = prepareMutationOverTimeData([
|
|
177
|
-
{ ...someSubstitutionEntry, proportion: atFilterMin },
|
|
178
|
-
{ ...anotherSubstitutionEntry, proportion: inFilter },
|
|
179
|
-
{ ...someDeletionEntry, proportion: inFilter },
|
|
180
|
-
]);
|
|
181
|
-
const result = getFilteredMutationOverTimeData({
|
|
182
|
-
data,
|
|
183
|
-
overallMutationData,
|
|
184
|
-
displayedSegments: [],
|
|
185
|
-
displayedMutationTypes: [],
|
|
186
|
-
proportionInterval,
|
|
187
|
-
hideGaps: false,
|
|
188
|
-
mutationFilterValue: { textFilter: '', annotationNameFilter: new Set() },
|
|
189
|
-
sequenceType: 'nucleotide',
|
|
190
|
-
annotationProvider: () => {
|
|
191
|
-
return [];
|
|
192
|
-
},
|
|
193
|
-
});
|
|
194
|
-
|
|
195
|
-
expect(result.getFirstAxisKeys()).to.deep.equal([someSubstitution, anotherSubstitution, someDeletion]);
|
|
196
|
-
});
|
|
197
|
-
|
|
198
|
-
it('should not remove mutations where overall proportion is at upper bound of filter', () => {
|
|
199
|
-
const { data, overallMutationData } = prepareMutationOverTimeData([
|
|
200
|
-
{ ...someSubstitutionEntry, proportion: atFilterMax },
|
|
201
|
-
{ ...anotherSubstitutionEntry, proportion: inFilter },
|
|
202
|
-
{ ...someDeletionEntry, proportion: inFilter },
|
|
203
|
-
]);
|
|
204
|
-
|
|
205
|
-
const result = getFilteredMutationOverTimeData({
|
|
206
|
-
data,
|
|
207
|
-
overallMutationData,
|
|
208
|
-
displayedSegments: [],
|
|
209
|
-
displayedMutationTypes: [],
|
|
210
|
-
proportionInterval,
|
|
211
|
-
hideGaps: false,
|
|
212
|
-
mutationFilterValue: { textFilter: '', annotationNameFilter: new Set() },
|
|
213
|
-
sequenceType: 'nucleotide',
|
|
214
|
-
annotationProvider: () => {
|
|
215
|
-
return [];
|
|
216
|
-
},
|
|
217
|
-
});
|
|
218
|
-
|
|
219
|
-
expect(result.getFirstAxisKeys()).to.deep.equal([someSubstitution, anotherSubstitution, someDeletion]);
|
|
220
|
-
});
|
|
221
|
-
|
|
222
|
-
it('should filter by mutation filter text value', () => {
|
|
223
|
-
const { data, overallMutationData } = prepareMutationOverTimeData([
|
|
224
|
-
someSubstitutionEntry,
|
|
225
|
-
anotherSubstitutionEntry,
|
|
226
|
-
someDeletionEntry,
|
|
227
|
-
]);
|
|
228
|
-
|
|
229
|
-
const result = getFilteredMutationOverTimeData({
|
|
230
|
-
data,
|
|
231
|
-
overallMutationData,
|
|
232
|
-
displayedSegments: [],
|
|
233
|
-
displayedMutationTypes: [],
|
|
234
|
-
proportionInterval,
|
|
235
|
-
hideGaps: false,
|
|
236
|
-
mutationFilterValue: { textFilter: '23T', annotationNameFilter: new Set() },
|
|
237
|
-
sequenceType: 'nucleotide',
|
|
238
|
-
annotationProvider: () => {
|
|
239
|
-
return [];
|
|
240
|
-
},
|
|
241
|
-
});
|
|
242
|
-
|
|
243
|
-
expect(result.getFirstAxisKeys()).to.deep.equal([someSubstitution]);
|
|
244
|
-
});
|
|
245
|
-
|
|
246
|
-
describe('should filter by annotation', () => {
|
|
247
|
-
const { data, overallMutationData } = prepareMutationOverTimeData([
|
|
248
|
-
someSubstitutionEntry,
|
|
249
|
-
anotherSubstitutionEntry,
|
|
250
|
-
someDeletionEntry,
|
|
251
|
-
]);
|
|
252
|
-
|
|
253
|
-
const expectFilteredValue = (filterValue: MutationFilter, annotations: MutationAnnotations) => {
|
|
254
|
-
const annotationProvider = getMutationAnnotationsProvider(getMutationAnnotationsContext(annotations));
|
|
255
|
-
|
|
256
|
-
const result = getFilteredMutationOverTimeData({
|
|
257
|
-
data,
|
|
258
|
-
overallMutationData,
|
|
259
|
-
displayedSegments: [],
|
|
260
|
-
displayedMutationTypes: [],
|
|
261
|
-
proportionInterval,
|
|
262
|
-
hideGaps: false,
|
|
263
|
-
mutationFilterValue: filterValue,
|
|
264
|
-
sequenceType: 'nucleotide',
|
|
265
|
-
annotationProvider,
|
|
266
|
-
});
|
|
267
|
-
|
|
268
|
-
expect(result.getFirstAxisKeys()).to.deep.equal([someSubstitution]);
|
|
269
|
-
};
|
|
270
|
-
|
|
271
|
-
it('with filter value in symbol', () => {
|
|
272
|
-
expectFilteredValue({ textFilter: '#', annotationNameFilter: new Set() }, [
|
|
273
|
-
{
|
|
274
|
-
name: 'Annotation 1',
|
|
275
|
-
description: 'Description 1',
|
|
276
|
-
symbol: '#',
|
|
277
|
-
nucleotideMutations: ['A123T'],
|
|
278
|
-
},
|
|
279
|
-
]);
|
|
280
|
-
});
|
|
281
|
-
|
|
282
|
-
it('with filter value in name', () => {
|
|
283
|
-
expectFilteredValue({ textFilter: 'Annota', annotationNameFilter: new Set() }, [
|
|
284
|
-
{
|
|
285
|
-
name: 'Annotation 1 #',
|
|
286
|
-
description: 'Description 1',
|
|
287
|
-
symbol: '+',
|
|
288
|
-
nucleotideMutations: ['A123T'],
|
|
289
|
-
},
|
|
290
|
-
]);
|
|
291
|
-
});
|
|
292
|
-
|
|
293
|
-
it('with filter value in name', () => {
|
|
294
|
-
expectFilteredValue({ textFilter: 'Descr', annotationNameFilter: new Set() }, [
|
|
295
|
-
{
|
|
296
|
-
name: 'Annotation 1',
|
|
297
|
-
description: 'Description 1',
|
|
298
|
-
symbol: '#',
|
|
299
|
-
nucleotideMutations: ['A123T'],
|
|
300
|
-
},
|
|
301
|
-
]);
|
|
302
|
-
});
|
|
303
|
-
|
|
304
|
-
it('with annotation name filter', () => {
|
|
305
|
-
expectFilteredValue({ textFilter: '', annotationNameFilter: new Set(['Annotation 1']) }, [
|
|
306
|
-
{
|
|
307
|
-
name: 'Annotation 1',
|
|
308
|
-
description: 'Description 1',
|
|
309
|
-
symbol: '#',
|
|
310
|
-
nucleotideMutations: ['A123T'],
|
|
311
|
-
},
|
|
312
|
-
]);
|
|
313
|
-
});
|
|
314
|
-
});
|
|
315
|
-
|
|
316
|
-
it('should remove date ranges that have no samples', () => {
|
|
317
|
-
const { data, overallMutationData } = prepareMutationOverTimeData([someSubstitutionEntry, someDeletionEntry]);
|
|
318
|
-
data.set(someSubstitution, anotherTemporal, emptyMutationOverTimeValue);
|
|
319
|
-
data.set(someDeletion, anotherTemporal, emptyMutationOverTimeValue);
|
|
320
|
-
|
|
321
|
-
const result = getFilteredMutationOverTimeData({
|
|
322
|
-
data,
|
|
323
|
-
overallMutationData,
|
|
324
|
-
displayedSegments: [],
|
|
325
|
-
displayedMutationTypes: [],
|
|
326
|
-
proportionInterval,
|
|
327
|
-
hideGaps: true,
|
|
328
|
-
mutationFilterValue: { textFilter: '', annotationNameFilter: new Set() },
|
|
329
|
-
sequenceType: 'nucleotide',
|
|
330
|
-
annotationProvider: () => {
|
|
331
|
-
return [];
|
|
332
|
-
},
|
|
333
|
-
});
|
|
334
|
-
|
|
335
|
-
expect(result.getSecondAxisKeys()).to.deep.equal([someTemporal]);
|
|
336
|
-
});
|
|
337
|
-
|
|
338
|
-
const belowFilter = 0.1;
|
|
339
|
-
const atFilterMin = 0.2;
|
|
340
|
-
const inFilter = 0.5;
|
|
341
|
-
const atFilterMax = 0.9;
|
|
342
|
-
const aboveFilter = 0.99;
|
|
343
|
-
const proportionInterval = { min: atFilterMin, max: atFilterMax };
|
|
344
|
-
|
|
345
|
-
const someSubstitution: Substitution = {
|
|
346
|
-
type: 'substitution',
|
|
347
|
-
valueAtReference: 'A',
|
|
348
|
-
substitutionValue: 'T',
|
|
349
|
-
code: 'A123T',
|
|
350
|
-
segment: 'someSegment',
|
|
351
|
-
position: 123,
|
|
352
|
-
};
|
|
353
|
-
const someSubstitutionEntry: SubstitutionEntry<Substitution> = {
|
|
354
|
-
type: 'substitution',
|
|
355
|
-
mutation: someSubstitution,
|
|
356
|
-
count: 234,
|
|
357
|
-
proportion: inFilter,
|
|
358
|
-
};
|
|
359
|
-
|
|
360
|
-
const anotherSubstitution: Substitution = {
|
|
361
|
-
type: 'substitution',
|
|
362
|
-
valueAtReference: 'G',
|
|
363
|
-
substitutionValue: 'C',
|
|
364
|
-
code: 'G345C',
|
|
365
|
-
segment: 'someOtherSegment',
|
|
366
|
-
position: 345,
|
|
367
|
-
};
|
|
368
|
-
const anotherSubstitutionEntry: SubstitutionEntry<Substitution> = {
|
|
369
|
-
type: 'substitution',
|
|
370
|
-
mutation: anotherSubstitution,
|
|
371
|
-
count: 456,
|
|
372
|
-
proportion: inFilter,
|
|
373
|
-
};
|
|
374
|
-
|
|
375
|
-
const someDeletion: Deletion = {
|
|
376
|
-
type: 'deletion',
|
|
377
|
-
valueAtReference: 'A',
|
|
378
|
-
segment: 'someSegment',
|
|
379
|
-
position: 567,
|
|
380
|
-
code: 'A123-',
|
|
381
|
-
};
|
|
382
|
-
const someDeletionEntry: DeletionEntry<Deletion> = {
|
|
383
|
-
type: 'deletion',
|
|
384
|
-
mutation: someDeletion,
|
|
385
|
-
count: 789,
|
|
386
|
-
proportion: inFilter,
|
|
387
|
-
};
|
|
388
|
-
const someTemporal = yearMonthDay('2021-01-01');
|
|
389
|
-
const anotherTemporal = yearMonthDay('2021-02-02');
|
|
390
|
-
const someMutationOverTimeValue = {
|
|
391
|
-
type: 'value',
|
|
392
|
-
count: 1,
|
|
393
|
-
proportion: inFilter,
|
|
394
|
-
totalCount: 10,
|
|
395
|
-
} satisfies ProportionValue;
|
|
396
|
-
const emptyMutationOverTimeValue = {
|
|
397
|
-
type: 'value',
|
|
398
|
-
count: 0,
|
|
399
|
-
proportion: NaN,
|
|
400
|
-
totalCount: 0,
|
|
401
|
-
} satisfies ProportionValue;
|
|
402
|
-
|
|
403
|
-
function prepareMutationOverTimeData(
|
|
404
|
-
mutationEntries: (SubstitutionEntry<Substitution> | DeletionEntry<Deletion>)[],
|
|
405
|
-
temporals: TemporalClass[] = [someTemporal, anotherTemporal],
|
|
406
|
-
) {
|
|
407
|
-
const data = new BaseMutationOverTimeDataMap();
|
|
408
|
-
|
|
409
|
-
temporals.forEach((temporal) => {
|
|
410
|
-
mutationEntries.forEach((entry) => {
|
|
411
|
-
data.set(entry.mutation, temporal, someMutationOverTimeValue);
|
|
412
|
-
});
|
|
413
|
-
});
|
|
414
|
-
|
|
415
|
-
return { data, overallMutationData: mutationEntries };
|
|
416
|
-
}
|
|
417
|
-
});
|