@genspectrum/dashboard-components 0.6.18 → 0.6.19

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 (108) hide show
  1. package/README.md +5 -12
  2. package/custom-elements.json +4 -4
  3. package/dist/assets/mutationOverTimeWorker-BdzqDqvO.js.map +1 -0
  4. package/dist/dashboard-components.js +216 -214
  5. package/dist/dashboard-components.js.map +1 -1
  6. package/dist/genspectrum-components.d.ts +40 -40
  7. package/dist/style.css +3 -2
  8. package/package.json +13 -2
  9. package/src/operator/FetchInsertionsOperator.ts +2 -2
  10. package/src/operator/FetchSubstitutionsOrDeletionsOperator.ts +3 -3
  11. package/src/preact/mutationComparison/fetchMutationData.spec.ts +3 -3
  12. package/src/preact/mutationComparison/getMutationComparisonTableData.spec.ts +11 -11
  13. package/src/preact/mutationComparison/getMutationComparisonTableData.ts +4 -4
  14. package/src/preact/mutationComparison/mutation-comparison-table.tsx +2 -2
  15. package/src/preact/mutationFilter/mutation-filter.tsx +27 -18
  16. package/src/preact/mutationFilter/parseAndValidateMutation.ts +4 -4
  17. package/src/preact/mutationFilter/parseMutation.spec.ts +17 -17
  18. package/src/preact/mutations/getInsertionsTableData.spec.ts +3 -3
  19. package/src/preact/mutations/getMutationsGridData.spec.ts +9 -9
  20. package/src/preact/mutations/getMutationsTableData.spec.ts +7 -7
  21. package/src/preact/mutations/mutations-insertions-table.tsx +3 -3
  22. package/src/preact/mutations/mutations-table.tsx +3 -3
  23. package/src/preact/mutationsOverTime/__mockData__/aminoAcidMutationsByDay.ts +45686 -0
  24. package/src/preact/mutationsOverTime/__mockData__/byWeek.ts +58989 -0
  25. package/src/preact/mutationsOverTime/__mockData__/defaultMockData.ts +103991 -0
  26. package/src/preact/mutationsOverTime/__mockData__/mockConversion.ts +54 -0
  27. package/src/preact/mutationsOverTime/__mockData__/showsMessageWhenTooManyMutations.ts +63690 -0
  28. package/src/preact/mutationsOverTime/getFilteredMutationsOverTime.spec.ts +176 -159
  29. package/src/preact/mutationsOverTime/getFilteredMutationsOverTimeData.ts +17 -59
  30. package/src/preact/mutationsOverTime/mutationOverTimeWorker.mock.ts +27 -0
  31. package/src/preact/mutationsOverTime/mutationOverTimeWorker.ts +29 -0
  32. package/src/preact/mutationsOverTime/mutations-over-time-grid.tsx +13 -14
  33. package/src/preact/mutationsOverTime/mutations-over-time.stories.tsx +9 -334
  34. package/src/preact/mutationsOverTime/mutations-over-time.tsx +68 -52
  35. package/src/preact/numberSequencesOverTime/getNumberOfSequencesOverTimeTableData.ts +3 -3
  36. package/src/preact/prevalenceOverTime/getPrevalenceOverTimeTableData.spec.ts +5 -5
  37. package/src/preact/prevalenceOverTime/prevalence-over-time-bubble-chart.tsx +1 -1
  38. package/src/preact/relativeGrowthAdvantage/relative-growth-advantage-chart.tsx +2 -2
  39. package/src/preact/shared/sort/sortInsertions.spec.ts +11 -11
  40. package/src/preact/shared/sort/sortInsertions.ts +2 -2
  41. package/src/preact/shared/sort/sortSubstitutionsAndDeletions.spec.ts +13 -13
  42. package/src/preact/shared/sort/sortSubstitutionsAndDeletions.ts +7 -4
  43. package/src/preact/webWorkers/useWebWorker.ts +51 -0
  44. package/src/preact/webWorkers/workerFunction.ts +14 -0
  45. package/src/query/queryAggregatedDataOverTime.ts +3 -3
  46. package/src/query/queryMutationsOverTime.spec.ts +272 -51
  47. package/src/query/queryMutationsOverTime.ts +114 -45
  48. package/src/query/queryPrevalenceOverTime.ts +2 -2
  49. package/src/query/queryRelativeGrowthAdvantage.ts +3 -3
  50. package/src/types.ts +25 -5
  51. package/src/utils/map2d.spec.ts +29 -1
  52. package/src/utils/map2d.ts +22 -1
  53. package/src/utils/mutations.spec.ts +20 -20
  54. package/src/utils/mutations.ts +80 -17
  55. package/src/utils/sort.ts +5 -2
  56. package/src/utils/temporal.spec.ts +27 -24
  57. package/src/utils/{temporal.ts → temporalClass.ts} +170 -72
  58. package/src/utils/temporalTestHelpers.ts +3 -3
  59. package/src/web-components/introduction.mdx +46 -0
  60. package/src/web-components/visualization/gs-mutations-over-time.stories.ts +6 -699
  61. package/src/web-components/visualization/gs-mutations-over-time.tsx +2 -2
  62. package/standalone-bundle/dashboard-components.js +13763 -13754
  63. package/standalone-bundle/dashboard-components.js.map +1 -1
  64. package/src/preact/mutationsOverTime/__mockData__/aggregated_2024_01.json +0 -13
  65. package/src/preact/mutationsOverTime/__mockData__/aggregated_2024_02.json +0 -13
  66. package/src/preact/mutationsOverTime/__mockData__/aggregated_2024_03.json +0 -13
  67. package/src/preact/mutationsOverTime/__mockData__/aggregated_2024_04.json +0 -13
  68. package/src/preact/mutationsOverTime/__mockData__/aggregated_2024_05.json +0 -13
  69. package/src/preact/mutationsOverTime/__mockData__/aggregated_2024_06.json +0 -13
  70. package/src/preact/mutationsOverTime/__mockData__/aggregated_2024_07.json +0 -13
  71. package/src/preact/mutationsOverTime/__mockData__/aggregated_20_01_2024.json +0 -13
  72. package/src/preact/mutationsOverTime/__mockData__/aggregated_21_01_2024.json +0 -13
  73. package/src/preact/mutationsOverTime/__mockData__/aggregated_22_01_2024.json +0 -13
  74. package/src/preact/mutationsOverTime/__mockData__/aggregated_23_01_2024.json +0 -13
  75. package/src/preact/mutationsOverTime/__mockData__/aggregated_24_01_2024.json +0 -13
  76. package/src/preact/mutationsOverTime/__mockData__/aggregated_25_01_2024.json +0 -13
  77. package/src/preact/mutationsOverTime/__mockData__/aggregated_26_01_2024.json +0 -13
  78. package/src/preact/mutationsOverTime/__mockData__/aggregated_byDay.json +0 -38
  79. package/src/preact/mutationsOverTime/__mockData__/aggregated_byWeek.json +0 -122
  80. package/src/preact/mutationsOverTime/__mockData__/aggregated_date.json +0 -642
  81. package/src/preact/mutationsOverTime/__mockData__/aggregated_tooManyMutations.json +0 -1470
  82. package/src/preact/mutationsOverTime/__mockData__/aggregated_tooManyMutations_total.json +0 -13
  83. package/src/preact/mutationsOverTime/__mockData__/aggregated_week3_2024.json +0 -13
  84. package/src/preact/mutationsOverTime/__mockData__/aggregated_week4_2024.json +0 -13
  85. package/src/preact/mutationsOverTime/__mockData__/aggregated_week5_2024.json +0 -13
  86. package/src/preact/mutationsOverTime/__mockData__/aggregated_week6_2024.json +0 -13
  87. package/src/preact/mutationsOverTime/__mockData__/aminoAcidMutations_20_01_2024.json +0 -6778
  88. package/src/preact/mutationsOverTime/__mockData__/aminoAcidMutations_21_01_2024.json +0 -7129
  89. package/src/preact/mutationsOverTime/__mockData__/aminoAcidMutations_22_01_2024.json +0 -4681
  90. package/src/preact/mutationsOverTime/__mockData__/aminoAcidMutations_23_01_2024.json +0 -10738
  91. package/src/preact/mutationsOverTime/__mockData__/aminoAcidMutations_24_01_2024.json +0 -11710
  92. package/src/preact/mutationsOverTime/__mockData__/aminoAcidMutations_25_01_2024.json +0 -11557
  93. package/src/preact/mutationsOverTime/__mockData__/aminoAcidMutations_26_01_2024.json +0 -8596
  94. package/src/preact/mutationsOverTime/__mockData__/aminoAcidMutations_byDayOverall.json +0 -4726
  95. package/src/preact/mutationsOverTime/__mockData__/nucleotideMutations_2024_01.json +0 -1747
  96. package/src/preact/mutationsOverTime/__mockData__/nucleotideMutations_2024_02.json +0 -1774
  97. package/src/preact/mutationsOverTime/__mockData__/nucleotideMutations_2024_03.json +0 -1819
  98. package/src/preact/mutationsOverTime/__mockData__/nucleotideMutations_2024_04.json +0 -1864
  99. package/src/preact/mutationsOverTime/__mockData__/nucleotideMutations_2024_05.json +0 -1927
  100. package/src/preact/mutationsOverTime/__mockData__/nucleotideMutations_2024_06.json +0 -1864
  101. package/src/preact/mutationsOverTime/__mockData__/nucleotideMutations_2024_07.json +0 -9
  102. package/src/preact/mutationsOverTime/__mockData__/nucleotideMutations_byMonthOverall.json +0 -11143
  103. package/src/preact/mutationsOverTime/__mockData__/nucleotideMutations_byWeekOverall.json +0 -9154
  104. package/src/preact/mutationsOverTime/__mockData__/nucleotideMutations_tooManyMutations.json +0 -16453
  105. package/src/preact/mutationsOverTime/__mockData__/nucleotideMutations_week3_2024.json +0 -8812
  106. package/src/preact/mutationsOverTime/__mockData__/nucleotideMutations_week4_2024.json +0 -9730
  107. package/src/preact/mutationsOverTime/__mockData__/nucleotideMutations_week5_2024.json +0 -9865
  108. package/src/preact/mutationsOverTime/__mockData__/nucleotideMutations_week6_2024.json +0 -11314
@@ -1,190 +1,207 @@
1
1
  import { describe, expect, it } from 'vitest';
2
2
 
3
- import { filterDisplayedSegments, filterMutationTypes, filterProportion } from './getFilteredMutationsOverTimeData';
3
+ import { getFilteredMutationOverTimeData } from './getFilteredMutationsOverTimeData';
4
4
  import { type MutationOverTimeMutationValue } from '../../query/queryMutationsOverTime';
5
+ import { type DeletionEntry, type SubstitutionEntry } from '../../types';
5
6
  import { Map2dBase } from '../../utils/map2d';
6
- import { Deletion, Substitution } from '../../utils/mutations';
7
- import { type Temporal } from '../../utils/temporal';
7
+ import { type Deletion, type Substitution } from '../../utils/mutations';
8
+ import { type TemporalClass } from '../../utils/temporalClass';
8
9
  import { yearMonthDay } from '../../utils/temporalTestHelpers';
9
10
 
10
11
  describe('getFilteredMutationOverTimeData', () => {
11
- describe('filterDisplayedSegments', () => {
12
- it('should filter by displayed segments', () => {
13
- const data = new Map2dBase<Substitution | Deletion, Temporal, MutationOverTimeMutationValue>();
14
-
15
- data.set(new Substitution('someSegment', 'A', 'T', 123), yearMonthDay('2021-01-01'), {
16
- count: 1,
17
- proportion: 0.1,
18
- totalCount: 10,
19
- });
20
- data.set(new Substitution('someOtherSegment', 'A', 'T', 123), yearMonthDay('2021-01-01'), {
21
- count: 2,
22
- proportion: 0.2,
23
- totalCount: 10,
24
- });
25
-
26
- filterDisplayedSegments(
27
- [
28
- { segment: 'someSegment', checked: false, label: 'Some Segment' },
29
- { segment: 'someOtherSegment', checked: true, label: 'Some Other Segment' },
30
- ],
31
- data,
32
- );
33
-
34
- expect(data.getFirstAxisKeys().length).to.equal(1);
35
- expect(data.getFirstAxisKeys()[0].segment).to.equal('someOtherSegment');
36
- });
12
+ it('should filter by displayed segments', () => {
13
+ const { data, overallMutationData } = prepareMutationOverTimeData([
14
+ someSubstitutionEntry,
15
+ anotherSubstitutionEntry,
16
+ someDeletionEntry,
17
+ ]);
18
+
19
+ const result = getFilteredMutationOverTimeData(
20
+ data,
21
+ overallMutationData,
22
+ [
23
+ { segment: 'someSegment', checked: false, label: 'Some Segment' },
24
+ { segment: 'someOtherSegment', checked: true, label: 'Some Other Segment' },
25
+ ],
26
+ [],
27
+ proportionInterval,
28
+ );
29
+
30
+ expect(result.getFirstAxisKeys()).to.deep.equal([anotherSubstitution]);
37
31
  });
38
32
 
39
- describe('filterMutationTypes', () => {
40
- it('should filter by mutation types', () => {
41
- const data = new Map2dBase<Substitution | Deletion, Temporal, MutationOverTimeMutationValue>();
33
+ it('should filter by mutation types', () => {
34
+ const { data, overallMutationData } = prepareMutationOverTimeData([
35
+ someSubstitutionEntry,
36
+ anotherSubstitutionEntry,
37
+ someDeletionEntry,
38
+ ]);
39
+
40
+ const result = getFilteredMutationOverTimeData(
41
+ data,
42
+ overallMutationData,
43
+ [],
44
+ [
45
+ {
46
+ type: 'substitution',
47
+ checked: false,
48
+ label: 'Substitution',
49
+ },
50
+ {
51
+ type: 'deletion',
52
+ checked: true,
53
+ label: 'Deletion',
54
+ },
55
+ ],
56
+ proportionInterval,
57
+ );
58
+
59
+ expect(result.getFirstAxisKeys()).to.deep.equal([someDeletion]);
60
+ });
42
61
 
43
- data.set(new Substitution('someSegment', 'A', 'T', 123), yearMonthDay('2021-01-01'), {
44
- count: 1,
45
- proportion: 0.1,
46
- totalCount: 10,
47
- });
48
- data.set(new Deletion('someOtherSegment', 'A', 123), yearMonthDay('2021-01-01'), {
49
- count: 2,
50
- proportion: 0.2,
51
- totalCount: 10,
52
- });
62
+ it('should remove mutations where overall proportion is below filter', () => {
63
+ const { data, overallMutationData } = prepareMutationOverTimeData([
64
+ { ...someSubstitutionEntry, proportion: belowFilter },
65
+ { ...anotherSubstitutionEntry, proportion: inFilter },
66
+ { ...someDeletionEntry, proportion: inFilter },
67
+ ]);
53
68
 
54
- filterMutationTypes(
55
- [
56
- { type: 'substitution', checked: false, label: 'Substitution' },
57
- { type: 'deletion', checked: true, label: 'Deletion' },
58
- ],
59
- data,
60
- );
69
+ const result = getFilteredMutationOverTimeData(data, overallMutationData, [], [], proportionInterval);
61
70
 
62
- expect(data.getFirstAxisKeys().length).to.equal(1);
63
- expect(data.getFirstAxisKeys()[0].type).to.equal('deletion');
64
- });
71
+ expect(result.getFirstAxisKeys()).to.deep.equal([anotherSubstitution, someDeletion]);
65
72
  });
66
73
 
67
- describe('filterProportion', () => {
68
- const belowFilter = 0.1;
69
- const atFilterMin = 0.2;
70
- const inFilter = 0.5;
71
- const atFilterMax = 0.9;
72
- const aboveFilter = 0.99;
73
- const proportionInterval = { min: atFilterMin, max: atFilterMax };
74
-
75
- const someSubstitution = new Substitution('someSegment', 'A', 'T', 123);
76
- const someOtherMutation = new Substitution('someOtherSegment', 'A', 'G', 9);
77
-
78
- it('should remove mutations where overall proportion is below filter', () => {
79
- const data = getMutationOverTimeData();
80
-
81
- filterProportion(data, getOverallMutationData(belowFilter), proportionInterval);
82
-
83
- expect(
84
- data.getAsArray({
85
- count: 0,
86
- proportion: 0,
87
- totalCount: 10,
88
- }),
89
- ).to.toHaveLength(0);
90
- });
91
-
92
- it('should remove mutations where overall proportion is above filter', () => {
93
- const data = getMutationOverTimeData();
74
+ it('should remove mutations where overall proportion is above filter', () => {
75
+ const { data, overallMutationData } = prepareMutationOverTimeData([
76
+ { ...someSubstitutionEntry, proportion: aboveFilter },
77
+ { ...anotherSubstitutionEntry, proportion: inFilter },
78
+ { ...someDeletionEntry, proportion: inFilter },
79
+ ]);
94
80
 
95
- filterProportion(data, getOverallMutationData(aboveFilter), proportionInterval);
81
+ const result = getFilteredMutationOverTimeData(data, overallMutationData, [], [], proportionInterval);
96
82
 
97
- expect(
98
- data.getAsArray({
99
- count: 0,
100
- proportion: 0,
101
- totalCount: 10,
102
- }),
103
- ).to.toHaveLength(0);
104
- });
83
+ expect(result.getFirstAxisKeys()).to.deep.equal([anotherSubstitution, someDeletion]);
84
+ });
105
85
 
106
- it('should remove mutations where overall proportion is missing', () => {
107
- const data = getMutationOverTimeData();
86
+ it('should not remove mutations where overall proportion is above filter but single proportion is below filter', () => {
87
+ const { data, overallMutationData } = prepareMutationOverTimeData([
88
+ someSubstitutionEntry,
89
+ anotherSubstitutionEntry,
90
+ someDeletionEntry,
91
+ ]);
92
+ data.set(someSubstitution, someTemporal, { ...someMutationOverTimeValue, proportion: belowFilter });
108
93
 
109
- filterProportion(data, getOverallMutationData(aboveFilter, someOtherMutation), proportionInterval);
94
+ const result = getFilteredMutationOverTimeData(data, overallMutationData, [], [], proportionInterval);
110
95
 
111
- expect(
112
- data.getAsArray({
113
- count: 0,
114
- proportion: 0,
115
- totalCount: 10,
116
- }),
117
- ).to.toHaveLength(0);
118
- });
96
+ expect(result.getFirstAxisKeys()).to.deep.equal([someSubstitution, anotherSubstitution, someDeletion]);
97
+ });
119
98
 
120
- it('should not remove mutation where overall proportion is at lower border of filter', () => {
121
- const data = getMutationOverTimeData();
99
+ it('should not remove mutations where overall proportion is below max but single proportion is above max', () => {
100
+ const { data, overallMutationData } = prepareMutationOverTimeData([
101
+ someSubstitutionEntry,
102
+ anotherSubstitutionEntry,
103
+ someDeletionEntry,
104
+ ]);
105
+ data.set(someSubstitution, someTemporal, { ...someMutationOverTimeValue, proportion: aboveFilter });
122
106
 
123
- filterProportion(data, getOverallMutationData(inFilter), proportionInterval);
107
+ const result = getFilteredMutationOverTimeData(data, overallMutationData, [], [], proportionInterval);
124
108
 
125
- expect(
126
- data.getRow(someSubstitution, {
127
- count: 0,
128
- proportion: 0,
129
- totalCount: 10,
130
- }),
131
- ).to.toHaveLength(2);
132
- });
109
+ expect(result.getFirstAxisKeys()).to.deep.equal([someSubstitution, anotherSubstitution, someDeletion]);
110
+ });
133
111
 
134
- it('should not remove mutation where overall proportion is within filter', () => {
135
- const data = getMutationOverTimeData();
112
+ it('should not remove mutations where overall proportion is at lower bound of filter', () => {
113
+ const { data, overallMutationData } = prepareMutationOverTimeData([
114
+ { ...someSubstitutionEntry, proportion: atFilterMin },
115
+ { ...anotherSubstitutionEntry, proportion: inFilter },
116
+ { ...someDeletionEntry, proportion: inFilter },
117
+ ]);
118
+ const result = getFilteredMutationOverTimeData(data, overallMutationData, [], [], proportionInterval);
136
119
 
137
- filterProportion(data, getOverallMutationData(inFilter), proportionInterval);
120
+ expect(result.getFirstAxisKeys()).to.deep.equal([someSubstitution, anotherSubstitution, someDeletion]);
121
+ });
138
122
 
139
- expect(
140
- data.getRow(someSubstitution, {
141
- count: 0,
142
- proportion: 0,
143
- totalCount: 10,
144
- }),
145
- ).to.toHaveLength(2);
146
- });
123
+ it('should not remove mutations where overall proportion is at upper bound of filter', () => {
124
+ const { data, overallMutationData } = prepareMutationOverTimeData([
125
+ { ...someSubstitutionEntry, proportion: atFilterMax },
126
+ { ...anotherSubstitutionEntry, proportion: inFilter },
127
+ { ...someDeletionEntry, proportion: inFilter },
128
+ ]);
147
129
 
148
- it('should not remove mutation where overall proportion is at upper border of filter', () => {
149
- const data = getMutationOverTimeData();
130
+ const result = getFilteredMutationOverTimeData(data, overallMutationData, [], [], proportionInterval);
150
131
 
151
- filterProportion(data, getOverallMutationData(inFilter), proportionInterval);
132
+ expect(result.getFirstAxisKeys()).to.deep.equal([someSubstitution, anotherSubstitution, someDeletion]);
133
+ });
152
134
 
153
- expect(
154
- data.getRow(someSubstitution, {
155
- count: 0,
156
- proportion: 0,
157
- totalCount: 10,
158
- }),
159
- ).to.toHaveLength(2);
135
+ const belowFilter = 0.1;
136
+ const atFilterMin = 0.2;
137
+ const inFilter = 0.5;
138
+ const atFilterMax = 0.9;
139
+ const aboveFilter = 0.99;
140
+ const proportionInterval = { min: atFilterMin, max: atFilterMax };
141
+
142
+ const someSubstitution: Substitution = {
143
+ type: 'substitution',
144
+ valueAtReference: 'A',
145
+ substitutionValue: 'T',
146
+ code: 'A123T',
147
+ segment: 'someSegment',
148
+ position: 123,
149
+ };
150
+ const someSubstitutionEntry: SubstitutionEntry<Substitution> = {
151
+ type: 'substitution',
152
+ mutation: someSubstitution,
153
+ count: 234,
154
+ proportion: inFilter,
155
+ };
156
+
157
+ const anotherSubstitution: Substitution = {
158
+ type: 'substitution',
159
+ valueAtReference: 'G',
160
+ substitutionValue: 'C',
161
+ code: 'G345C',
162
+ segment: 'someOtherSegment',
163
+ position: 345,
164
+ };
165
+ const anotherSubstitutionEntry: SubstitutionEntry<Substitution> = {
166
+ type: 'substitution',
167
+ mutation: anotherSubstitution,
168
+ count: 456,
169
+ proportion: inFilter,
170
+ };
171
+
172
+ const someDeletion: Deletion = {
173
+ type: 'deletion',
174
+ valueAtReference: 'A',
175
+ segment: 'someSegment',
176
+ position: 567,
177
+ code: 'A123-',
178
+ };
179
+ const someDeletionEntry: DeletionEntry<Deletion> = {
180
+ type: 'deletion',
181
+ mutation: someDeletion,
182
+ count: 789,
183
+ proportion: inFilter,
184
+ };
185
+ const someTemporal = yearMonthDay('2021-01-01');
186
+ const anotherTemporal = yearMonthDay('2021-02-02');
187
+ const someMutationOverTimeValue = {
188
+ count: 1,
189
+ proportion: inFilter,
190
+ totalCount: 10,
191
+ };
192
+
193
+ function prepareMutationOverTimeData(
194
+ mutationEntries: (SubstitutionEntry<Substitution> | DeletionEntry<Deletion>)[],
195
+ temporals: TemporalClass[] = [someTemporal, anotherTemporal],
196
+ ) {
197
+ const data = new Map2dBase<Substitution | Deletion, TemporalClass, MutationOverTimeMutationValue>();
198
+
199
+ temporals.forEach((temporal) => {
200
+ mutationEntries.forEach((entry) => {
201
+ data.set(entry.mutation, temporal, someMutationOverTimeValue);
202
+ });
160
203
  });
161
204
 
162
- function getMutationOverTimeData() {
163
- const data = new Map2dBase<Substitution | Deletion, Temporal, MutationOverTimeMutationValue>();
164
- data.set(someSubstitution, yearMonthDay('2021-01-01'), {
165
- count: 1,
166
- proportion: 0.1,
167
- totalCount: 10,
168
- });
169
- data.set(someSubstitution, yearMonthDay('2021-02-02'), {
170
- count: 99,
171
- proportion: 0.99,
172
- totalCount: 10,
173
- });
174
- return data;
175
- }
176
-
177
- function getOverallMutationData(proportion: number = 0.1, mutation: Substitution = someSubstitution) {
178
- return {
179
- content: [
180
- {
181
- type: 'substitution' as const,
182
- count: -1,
183
- mutation,
184
- proportion,
185
- },
186
- ],
187
- };
188
- }
189
- });
205
+ return { data, overallMutationData: mutationEntries };
206
+ }
190
207
  });
@@ -1,76 +1,34 @@
1
- import { type Dataset } from '../../operator/Dataset';
2
- import { type MutationOverTimeDataGroupedByMutation } from '../../query/queryMutationsOverTime';
3
- import { type DeletionEntry, type SubstitutionEntry } from '../../types';
1
+ import { type MutationOverTimeData } from './mutations-over-time';
2
+ import { type SubstitutionOrDeletionEntry } from '../../types';
4
3
  import { Map2dView } from '../../utils/map2d';
4
+ import type { Deletion, Substitution } from '../../utils/mutations';
5
5
  import type { DisplayedMutationType } from '../components/mutation-type-selector';
6
6
  import type { DisplayedSegment } from '../components/segment-selector';
7
7
 
8
8
  export function getFilteredMutationOverTimeData(
9
- data: MutationOverTimeDataGroupedByMutation,
10
- overallMutationData: Dataset<SubstitutionEntry | DeletionEntry>,
9
+ data: MutationOverTimeData,
10
+ overallMutationData: SubstitutionOrDeletionEntry<Substitution, Deletion>[],
11
11
  displayedSegments: DisplayedSegment[],
12
12
  displayedMutationTypes: DisplayedMutationType[],
13
13
  proportionInterval: { min: number; max: number },
14
14
  ) {
15
15
  const filteredData = new Map2dView(data);
16
- filterDisplayedSegments(displayedSegments, filteredData);
17
- filterMutationTypes(displayedMutationTypes, filteredData);
18
- filterProportion(filteredData, overallMutationData, proportionInterval);
19
16
 
20
- return filteredData;
21
- }
22
-
23
- export function filterDisplayedSegments(
24
- displayedSegments: DisplayedSegment[],
25
- data: MutationOverTimeDataGroupedByMutation,
26
- ) {
27
- displayedSegments.forEach((segment) => {
28
- if (!segment.checked) {
29
- data.getFirstAxisKeys().forEach((mutation) => {
30
- if (mutation.segment === segment.segment) {
31
- data.deleteRow(mutation);
32
- }
33
- });
17
+ const mutationsToFilterOut = overallMutationData.filter((entry) => {
18
+ if (entry.proportion < proportionInterval.min || entry.proportion > proportionInterval.max) {
19
+ return true;
34
20
  }
35
- });
36
- }
37
-
38
- export function filterMutationTypes(
39
- displayedMutationTypes: DisplayedMutationType[],
40
- data: MutationOverTimeDataGroupedByMutation,
41
- ) {
42
- displayedMutationTypes.forEach((mutationType) => {
43
- if (!mutationType.checked) {
44
- data.getFirstAxisKeys().forEach((mutation) => {
45
- if (mutationType.type === mutation.type) {
46
- data.deleteRow(mutation);
47
- }
48
- });
21
+ if (displayedSegments.some((segment) => segment.segment === entry.mutation.segment && !segment.checked)) {
22
+ return true;
49
23
  }
24
+ return displayedMutationTypes.some(
25
+ (mutationType) => mutationType.type === entry.mutation.type && !mutationType.checked,
26
+ );
50
27
  });
51
- }
52
-
53
- export function filterProportion(
54
- data: MutationOverTimeDataGroupedByMutation,
55
- overallMutationData: Dataset<SubstitutionEntry | DeletionEntry>,
56
- proportionInterval: {
57
- min: number;
58
- max: number;
59
- },
60
- ) {
61
- const overallProportionsByMutation = overallMutationData.content.reduce(
62
- (acc, { mutation, proportion }) => ({
63
- ...acc,
64
- [mutation.toString()]: proportion,
65
- }),
66
- {} as Record<string, number>,
67
- );
68
28
 
69
- data.getFirstAxisKeys().forEach((mutation) => {
70
- const overallProportion = overallProportionsByMutation[mutation.toString()] || -1;
71
-
72
- if (overallProportion < proportionInterval.min || overallProportion > proportionInterval.max) {
73
- data.deleteRow(mutation);
74
- }
29
+ mutationsToFilterOut.forEach((entry) => {
30
+ filteredData.deleteRow(entry.mutation);
75
31
  });
32
+
33
+ return filteredData;
76
34
  }
@@ -0,0 +1,27 @@
1
+ import { aminoAcidMutationsByDay } from './__mockData__/aminoAcidMutationsByDay';
2
+ import { getMutationOverTimeWorkerFunction, type MutationOverTimeWorkerResponse } from './mutationOverTimeWorker';
3
+ import { type MutationOverTimeQuery } from '../../query/queryMutationsOverTime';
4
+ import { workerFunction } from '../webWorkers/workerFunction';
5
+ import { byWeek } from './__mockData__/byWeek';
6
+ import { defaultMockData } from './__mockData__/defaultMockData';
7
+ import { getMutationOverTimeMock } from './__mockData__/mockConversion';
8
+ import { showsMessageWhenTooManyMutations } from './__mockData__/showsMessageWhenTooManyMutations';
9
+
10
+ const mockQueries: { query: MutationOverTimeQuery; response: MutationOverTimeWorkerResponse }[] = [
11
+ getMutationOverTimeMock(defaultMockData),
12
+ getMutationOverTimeMock(showsMessageWhenTooManyMutations),
13
+ getMutationOverTimeMock(byWeek),
14
+ getMutationOverTimeMock(aminoAcidMutationsByDay),
15
+ ];
16
+
17
+ self.onmessage = async function (event: MessageEvent<MutationOverTimeQuery>) {
18
+ await workerFunction(async () => {
19
+ const query = mockQueries.find((mockQuery) => JSON.stringify(mockQuery.query) === JSON.stringify(event.data));
20
+
21
+ if (query !== undefined) {
22
+ return query.response;
23
+ }
24
+
25
+ return await getMutationOverTimeWorkerFunction(event);
26
+ });
27
+ };
@@ -0,0 +1,29 @@
1
+ import {
2
+ type MutationOverTimeMutationValue,
3
+ type MutationOverTimeQuery,
4
+ queryMutationsOverTimeData,
5
+ } from '../../query/queryMutationsOverTime';
6
+ import type { SubstitutionOrDeletionEntry } from '../../types';
7
+ import { type Map2DContents } from '../../utils/map2d';
8
+ import type { Deletion, Substitution } from '../../utils/mutations';
9
+ import type { Temporal } from '../../utils/temporalClass';
10
+ import { workerFunction } from '../webWorkers/workerFunction';
11
+
12
+ export type MutationOverTimeWorkerResponse = {
13
+ overallMutationData: SubstitutionOrDeletionEntry<Substitution, Deletion>[];
14
+ mutationOverTimeSerialized: Map2DContents<Substitution | Deletion, Temporal, MutationOverTimeMutationValue>;
15
+ };
16
+
17
+ export async function getMutationOverTimeWorkerFunction(event: MessageEvent<MutationOverTimeQuery>) {
18
+ const mutationOverTimeData = await queryMutationsOverTimeData(event.data);
19
+
20
+ const workerResponse: MutationOverTimeWorkerResponse = {
21
+ overallMutationData: mutationOverTimeData.overallMutationData,
22
+ mutationOverTimeSerialized: mutationOverTimeData.mutationOverTimeData.getContents(),
23
+ };
24
+ return workerResponse;
25
+ }
26
+
27
+ self.onmessage = async function (event: MessageEvent<MutationOverTimeQuery>) {
28
+ await workerFunction(() => getMutationOverTimeWorkerFunction(event));
29
+ };
@@ -1,19 +1,16 @@
1
1
  import { Fragment, type FunctionComponent, type RefObject } from 'preact';
2
2
  import { useEffect, useRef, useState } from 'preact/hooks';
3
3
 
4
- import {
5
- type MutationOverTimeDataGroupedByMutation,
6
- type MutationOverTimeMutationValue,
7
- } from '../../query/queryMutationsOverTime';
4
+ import { type MutationOverTimeData } from './mutations-over-time';
5
+ import { type MutationOverTimeMutationValue } from '../../query/queryMutationsOverTime';
8
6
  import { type Deletion, type Substitution } from '../../utils/mutations';
9
- import { compareTemporal, type Temporal, YearMonthDay } from '../../utils/temporal';
7
+ import { toTemporalClass, type Temporal, type TemporalClass, YearMonthDayClass } from '../../utils/temporalClass';
10
8
  import { type ColorScale, getColorWithingScale, getTextColorForScale } from '../components/color-scale-selector';
11
9
  import Tooltip, { type TooltipPosition } from '../components/tooltip';
12
- import { sortSubstitutionsAndDeletions } from '../shared/sort/sortSubstitutionsAndDeletions';
13
10
  import { formatProportion } from '../shared/table/formatProportion';
14
11
 
15
12
  export interface MutationsOverTimeGridProps {
16
- data: MutationOverTimeDataGroupedByMutation;
13
+ data: MutationOverTimeData;
17
14
  colorScale: ColorScale;
18
15
  }
19
16
 
@@ -21,10 +18,10 @@ const MAX_NUMBER_OF_GRID_ROWS = 100;
21
18
  const MUTATION_CELL_WIDTH_REM = 8;
22
19
 
23
20
  const MutationsOverTimeGrid: FunctionComponent<MutationsOverTimeGridProps> = ({ data, colorScale }) => {
24
- const allMutations = data.getFirstAxisKeys().sort(sortSubstitutionsAndDeletions);
21
+ const allMutations = data.getFirstAxisKeys();
25
22
  const shownMutations = allMutations.slice(0, MAX_NUMBER_OF_GRID_ROWS);
26
23
 
27
- const dates = data.getSecondAxisKeys().sort((a, b) => compareTemporal(a, b));
24
+ const dates = data.getSecondAxisKeys();
28
25
 
29
26
  const [showProportionText, setShowProportionText] = useState(false);
30
27
  const gridRef = useRef<HTMLDivElement>(null);
@@ -128,12 +125,14 @@ const ProportionCell: FunctionComponent<{
128
125
  showProportionText: boolean;
129
126
  colorScale: ColorScale;
130
127
  }> = ({ value, mutation, date, tooltipPosition, showProportionText, colorScale }) => {
128
+ const dateClass = toTemporalClass(date);
129
+
131
130
  const tooltipContent = (
132
131
  <div>
133
132
  <p>
134
- <span className='font-bold'>{date.englishName()}</span>
133
+ <span className='font-bold'>{dateClass.englishName()}</span>
135
134
  </p>
136
- <p>({timeIntervalDisplay(date)})</p>
135
+ <p>({timeIntervalDisplay(dateClass)})</p>
137
136
  <p>{mutation.code}</p>
138
137
  <p>Proportion: {formatProportion(value.proportion)}</p>
139
138
  <p>
@@ -159,8 +158,8 @@ const ProportionCell: FunctionComponent<{
159
158
  );
160
159
  };
161
160
 
162
- const timeIntervalDisplay = (date: Temporal) => {
163
- if (date instanceof YearMonthDay) {
161
+ const timeIntervalDisplay = (date: TemporalClass) => {
162
+ if (date instanceof YearMonthDayClass) {
164
163
  return date.toString();
165
164
  }
166
165
 
@@ -168,7 +167,7 @@ const timeIntervalDisplay = (date: Temporal) => {
168
167
  };
169
168
 
170
169
  const MutationCell: FunctionComponent<{ mutation: Substitution | Deletion }> = ({ mutation }) => {
171
- return <div className='text-center'>{mutation.toString()}</div>;
170
+ return <div className='text-center'>{mutation.code}</div>;
172
171
  };
173
172
 
174
173
  export default MutationsOverTimeGrid;