@genspectrum/dashboard-components 1.11.0 → 1.12.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/dist/assets/mutationOverTimeWorker-f8Kp0S6V.js.map +1 -0
- package/dist/components.d.ts +53 -53
- package/dist/components.js +88 -36
- package/dist/components.js.map +1 -1
- package/dist/util.d.ts +53 -53
- package/package.json +1 -1
- package/src/lapisApi/lapisTypes.ts +1 -0
- package/src/preact/mutationsOverTime/getFilteredMutationsOverTimeData.ts +1 -1
- package/src/preact/mutationsOverTime/mutations-over-time-grid-tooltip.stories.tsx +47 -0
- package/src/preact/mutationsOverTime/mutations-over-time-grid-tooltip.tsx +64 -28
- package/src/preact/mutationsOverTime/mutations-over-time-grid.tsx +2 -2
- package/src/preact/mutationsOverTime/mutations-over-time.tsx +2 -2
- package/src/query/queryMutationsOverTime.ts +22 -15
- package/src/query/queryMutationsOverTimeNewEndpoint.spec.ts +100 -291
- package/src/web-components/visualization/gs-mutation-comparison.tsx +2 -2
- package/standalone-bundle/assets/mutationOverTimeWorker-AhhjjklP.js.map +1 -0
- package/standalone-bundle/dashboard-components.js +1822 -1769
- package/standalone-bundle/dashboard-components.js.map +1 -1
- package/dist/assets/mutationOverTimeWorker-dhufsWQ2.js.map +0 -1
- package/standalone-bundle/assets/mutationOverTimeWorker-CGqPKySO.js.map +0 -1
package/dist/util.d.ts
CHANGED
|
@@ -971,11 +971,7 @@ declare global {
|
|
|
971
971
|
|
|
972
972
|
declare global {
|
|
973
973
|
interface HTMLElementTagNameMap {
|
|
974
|
-
'gs-
|
|
975
|
-
}
|
|
976
|
-
interface HTMLElementEventMap {
|
|
977
|
-
[gsEventNames.dateRangeFilterChanged]: CustomEvent<Record<string, string>>;
|
|
978
|
-
[gsEventNames.dateRangeOptionChanged]: DateRangeOptionChangedEvent;
|
|
974
|
+
'gs-genome-data-viewer': GenomeDataViewerComponent;
|
|
979
975
|
}
|
|
980
976
|
}
|
|
981
977
|
|
|
@@ -983,7 +979,7 @@ declare global {
|
|
|
983
979
|
declare global {
|
|
984
980
|
namespace JSX {
|
|
985
981
|
interface IntrinsicElements {
|
|
986
|
-
'gs-
|
|
982
|
+
'gs-genome-data-viewer': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
|
|
987
983
|
}
|
|
988
984
|
}
|
|
989
985
|
}
|
|
@@ -991,10 +987,7 @@ declare global {
|
|
|
991
987
|
|
|
992
988
|
declare global {
|
|
993
989
|
interface HTMLElementTagNameMap {
|
|
994
|
-
'gs-
|
|
995
|
-
}
|
|
996
|
-
interface HTMLElementEventMap {
|
|
997
|
-
[gsEventNames.locationChanged]: LocationChangedEvent;
|
|
990
|
+
'gs-mutation-comparison': MutationComparisonComponent;
|
|
998
991
|
}
|
|
999
992
|
}
|
|
1000
993
|
|
|
@@ -1002,7 +995,7 @@ declare global {
|
|
|
1002
995
|
declare global {
|
|
1003
996
|
namespace JSX {
|
|
1004
997
|
interface IntrinsicElements {
|
|
1005
|
-
'gs-
|
|
998
|
+
'gs-mutation-comparison': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
|
|
1006
999
|
}
|
|
1007
1000
|
}
|
|
1008
1001
|
}
|
|
@@ -1010,10 +1003,7 @@ declare global {
|
|
|
1010
1003
|
|
|
1011
1004
|
declare global {
|
|
1012
1005
|
interface HTMLElementTagNameMap {
|
|
1013
|
-
'gs-
|
|
1014
|
-
}
|
|
1015
|
-
interface HTMLElementEventMap {
|
|
1016
|
-
[gsEventNames.textFilterChanged]: TextFilterChangedEvent;
|
|
1006
|
+
'gs-mutations': MutationsComponent;
|
|
1017
1007
|
}
|
|
1018
1008
|
}
|
|
1019
1009
|
|
|
@@ -1021,7 +1011,7 @@ declare global {
|
|
|
1021
1011
|
declare global {
|
|
1022
1012
|
namespace JSX {
|
|
1023
1013
|
interface IntrinsicElements {
|
|
1024
|
-
'gs-
|
|
1014
|
+
'gs-mutations': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
|
|
1025
1015
|
}
|
|
1026
1016
|
}
|
|
1027
1017
|
}
|
|
@@ -1029,11 +1019,7 @@ declare global {
|
|
|
1029
1019
|
|
|
1030
1020
|
declare global {
|
|
1031
1021
|
interface HTMLElementTagNameMap {
|
|
1032
|
-
'gs-
|
|
1033
|
-
}
|
|
1034
|
-
interface HTMLElementEventMap {
|
|
1035
|
-
[gsEventNames.lineageFilterChanged]: LineageFilterChangedEvent;
|
|
1036
|
-
[gsEventNames.lineageFilterMultiChanged]: LineageMultiFilterChangedEvent;
|
|
1022
|
+
'gs-relative-growth-advantage': RelativeGrowthAdvantageComponent;
|
|
1037
1023
|
}
|
|
1038
1024
|
}
|
|
1039
1025
|
|
|
@@ -1041,7 +1027,7 @@ declare global {
|
|
|
1041
1027
|
declare global {
|
|
1042
1028
|
namespace JSX {
|
|
1043
1029
|
interface IntrinsicElements {
|
|
1044
|
-
'gs-
|
|
1030
|
+
'gs-relative-growth-advantage': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
|
|
1045
1031
|
}
|
|
1046
1032
|
}
|
|
1047
1033
|
}
|
|
@@ -1049,10 +1035,7 @@ declare global {
|
|
|
1049
1035
|
|
|
1050
1036
|
declare global {
|
|
1051
1037
|
interface HTMLElementTagNameMap {
|
|
1052
|
-
'gs-
|
|
1053
|
-
}
|
|
1054
|
-
interface HTMLElementEventMap {
|
|
1055
|
-
[gsEventNames.mutationFilterChanged]: CustomEvent<MutationsFilter>;
|
|
1038
|
+
'gs-prevalence-over-time': PrevalenceOverTimeComponent;
|
|
1056
1039
|
}
|
|
1057
1040
|
}
|
|
1058
1041
|
|
|
@@ -1060,7 +1043,7 @@ declare global {
|
|
|
1060
1043
|
declare global {
|
|
1061
1044
|
namespace JSX {
|
|
1062
1045
|
interface IntrinsicElements {
|
|
1063
|
-
'gs-
|
|
1046
|
+
'gs-prevalence-over-time': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
|
|
1064
1047
|
}
|
|
1065
1048
|
}
|
|
1066
1049
|
}
|
|
@@ -1068,11 +1051,7 @@ declare global {
|
|
|
1068
1051
|
|
|
1069
1052
|
declare global {
|
|
1070
1053
|
interface HTMLElementTagNameMap {
|
|
1071
|
-
'gs-
|
|
1072
|
-
}
|
|
1073
|
-
interface HTMLElementEventMap {
|
|
1074
|
-
[gsEventNames.numberRangeFilterChanged]: NumberRangeFilterChangedEvent;
|
|
1075
|
-
[gsEventNames.numberRangeValueChanged]: NumberRangeValueChangedEvent;
|
|
1054
|
+
'gs-aggregate': AggregateComponent;
|
|
1076
1055
|
}
|
|
1077
1056
|
}
|
|
1078
1057
|
|
|
@@ -1080,7 +1059,7 @@ declare global {
|
|
|
1080
1059
|
declare global {
|
|
1081
1060
|
namespace JSX {
|
|
1082
1061
|
interface IntrinsicElements {
|
|
1083
|
-
'gs-
|
|
1062
|
+
'gs-aggregate': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
|
|
1084
1063
|
}
|
|
1085
1064
|
}
|
|
1086
1065
|
}
|
|
@@ -1088,7 +1067,7 @@ declare global {
|
|
|
1088
1067
|
|
|
1089
1068
|
declare global {
|
|
1090
1069
|
interface HTMLElementTagNameMap {
|
|
1091
|
-
'gs-
|
|
1070
|
+
'gs-number-sequences-over-time': NumberSequencesOverTimeComponent;
|
|
1092
1071
|
}
|
|
1093
1072
|
}
|
|
1094
1073
|
|
|
@@ -1096,7 +1075,7 @@ declare global {
|
|
|
1096
1075
|
declare global {
|
|
1097
1076
|
namespace JSX {
|
|
1098
1077
|
interface IntrinsicElements {
|
|
1099
|
-
'gs-
|
|
1078
|
+
'gs-number-sequences-over-time': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
|
|
1100
1079
|
}
|
|
1101
1080
|
}
|
|
1102
1081
|
}
|
|
@@ -1104,7 +1083,7 @@ declare global {
|
|
|
1104
1083
|
|
|
1105
1084
|
declare global {
|
|
1106
1085
|
interface HTMLElementTagNameMap {
|
|
1107
|
-
'gs-
|
|
1086
|
+
'gs-statistics': StatisticsComponent;
|
|
1108
1087
|
}
|
|
1109
1088
|
}
|
|
1110
1089
|
|
|
@@ -1112,7 +1091,7 @@ declare global {
|
|
|
1112
1091
|
declare global {
|
|
1113
1092
|
namespace JSX {
|
|
1114
1093
|
interface IntrinsicElements {
|
|
1115
|
-
'gs-
|
|
1094
|
+
'gs-statistics': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
|
|
1116
1095
|
}
|
|
1117
1096
|
}
|
|
1118
1097
|
}
|
|
@@ -1120,7 +1099,7 @@ declare global {
|
|
|
1120
1099
|
|
|
1121
1100
|
declare global {
|
|
1122
1101
|
interface HTMLElementTagNameMap {
|
|
1123
|
-
'gs-
|
|
1102
|
+
'gs-sequences-by-location': SequencesByLocationComponent;
|
|
1124
1103
|
}
|
|
1125
1104
|
}
|
|
1126
1105
|
|
|
@@ -1128,7 +1107,7 @@ declare global {
|
|
|
1128
1107
|
declare global {
|
|
1129
1108
|
namespace JSX {
|
|
1130
1109
|
interface IntrinsicElements {
|
|
1131
|
-
'gs-
|
|
1110
|
+
'gs-sequences-by-location': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
|
|
1132
1111
|
}
|
|
1133
1112
|
}
|
|
1134
1113
|
}
|
|
@@ -1136,7 +1115,7 @@ declare global {
|
|
|
1136
1115
|
|
|
1137
1116
|
declare global {
|
|
1138
1117
|
interface HTMLElementTagNameMap {
|
|
1139
|
-
'gs-
|
|
1118
|
+
'gs-mutations-over-time': MutationsOverTimeComponent;
|
|
1140
1119
|
}
|
|
1141
1120
|
}
|
|
1142
1121
|
|
|
@@ -1144,7 +1123,7 @@ declare global {
|
|
|
1144
1123
|
declare global {
|
|
1145
1124
|
namespace JSX {
|
|
1146
1125
|
interface IntrinsicElements {
|
|
1147
|
-
'gs-
|
|
1126
|
+
'gs-mutations-over-time': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
|
|
1148
1127
|
}
|
|
1149
1128
|
}
|
|
1150
1129
|
}
|
|
@@ -1152,7 +1131,11 @@ declare global {
|
|
|
1152
1131
|
|
|
1153
1132
|
declare global {
|
|
1154
1133
|
interface HTMLElementTagNameMap {
|
|
1155
|
-
'gs-
|
|
1134
|
+
'gs-date-range-filter': DateRangeFilterComponent;
|
|
1135
|
+
}
|
|
1136
|
+
interface HTMLElementEventMap {
|
|
1137
|
+
[gsEventNames.dateRangeFilterChanged]: CustomEvent<Record<string, string>>;
|
|
1138
|
+
[gsEventNames.dateRangeOptionChanged]: DateRangeOptionChangedEvent;
|
|
1156
1139
|
}
|
|
1157
1140
|
}
|
|
1158
1141
|
|
|
@@ -1160,7 +1143,7 @@ declare global {
|
|
|
1160
1143
|
declare global {
|
|
1161
1144
|
namespace JSX {
|
|
1162
1145
|
interface IntrinsicElements {
|
|
1163
|
-
'gs-
|
|
1146
|
+
'gs-date-range-filter': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
|
|
1164
1147
|
}
|
|
1165
1148
|
}
|
|
1166
1149
|
}
|
|
@@ -1168,7 +1151,10 @@ declare global {
|
|
|
1168
1151
|
|
|
1169
1152
|
declare global {
|
|
1170
1153
|
interface HTMLElementTagNameMap {
|
|
1171
|
-
'gs-
|
|
1154
|
+
'gs-text-filter': TextFilterComponent;
|
|
1155
|
+
}
|
|
1156
|
+
interface HTMLElementEventMap {
|
|
1157
|
+
[gsEventNames.textFilterChanged]: TextFilterChangedEvent;
|
|
1172
1158
|
}
|
|
1173
1159
|
}
|
|
1174
1160
|
|
|
@@ -1176,7 +1162,7 @@ declare global {
|
|
|
1176
1162
|
declare global {
|
|
1177
1163
|
namespace JSX {
|
|
1178
1164
|
interface IntrinsicElements {
|
|
1179
|
-
'gs-
|
|
1165
|
+
'gs-text-filter': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
|
|
1180
1166
|
}
|
|
1181
1167
|
}
|
|
1182
1168
|
}
|
|
@@ -1184,7 +1170,10 @@ declare global {
|
|
|
1184
1170
|
|
|
1185
1171
|
declare global {
|
|
1186
1172
|
interface HTMLElementTagNameMap {
|
|
1187
|
-
'gs-
|
|
1173
|
+
'gs-location-filter': LocationFilterComponent;
|
|
1174
|
+
}
|
|
1175
|
+
interface HTMLElementEventMap {
|
|
1176
|
+
[gsEventNames.locationChanged]: LocationChangedEvent;
|
|
1188
1177
|
}
|
|
1189
1178
|
}
|
|
1190
1179
|
|
|
@@ -1192,7 +1181,7 @@ declare global {
|
|
|
1192
1181
|
declare global {
|
|
1193
1182
|
namespace JSX {
|
|
1194
1183
|
interface IntrinsicElements {
|
|
1195
|
-
'gs-
|
|
1184
|
+
'gs-location-filter': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
|
|
1196
1185
|
}
|
|
1197
1186
|
}
|
|
1198
1187
|
}
|
|
@@ -1200,7 +1189,10 @@ declare global {
|
|
|
1200
1189
|
|
|
1201
1190
|
declare global {
|
|
1202
1191
|
interface HTMLElementTagNameMap {
|
|
1203
|
-
'gs-
|
|
1192
|
+
'gs-mutation-filter': MutationFilterComponent;
|
|
1193
|
+
}
|
|
1194
|
+
interface HTMLElementEventMap {
|
|
1195
|
+
[gsEventNames.mutationFilterChanged]: CustomEvent<MutationsFilter>;
|
|
1204
1196
|
}
|
|
1205
1197
|
}
|
|
1206
1198
|
|
|
@@ -1208,7 +1200,7 @@ declare global {
|
|
|
1208
1200
|
declare global {
|
|
1209
1201
|
namespace JSX {
|
|
1210
1202
|
interface IntrinsicElements {
|
|
1211
|
-
'gs-
|
|
1203
|
+
'gs-mutation-filter': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
|
|
1212
1204
|
}
|
|
1213
1205
|
}
|
|
1214
1206
|
}
|
|
@@ -1216,7 +1208,11 @@ declare global {
|
|
|
1216
1208
|
|
|
1217
1209
|
declare global {
|
|
1218
1210
|
interface HTMLElementTagNameMap {
|
|
1219
|
-
'gs-
|
|
1211
|
+
'gs-number-range-filter': NumberRangeFilterComponent;
|
|
1212
|
+
}
|
|
1213
|
+
interface HTMLElementEventMap {
|
|
1214
|
+
[gsEventNames.numberRangeFilterChanged]: NumberRangeFilterChangedEvent;
|
|
1215
|
+
[gsEventNames.numberRangeValueChanged]: NumberRangeValueChangedEvent;
|
|
1220
1216
|
}
|
|
1221
1217
|
}
|
|
1222
1218
|
|
|
@@ -1224,7 +1220,7 @@ declare global {
|
|
|
1224
1220
|
declare global {
|
|
1225
1221
|
namespace JSX {
|
|
1226
1222
|
interface IntrinsicElements {
|
|
1227
|
-
'gs-
|
|
1223
|
+
'gs-number-range-filter': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
|
|
1228
1224
|
}
|
|
1229
1225
|
}
|
|
1230
1226
|
}
|
|
@@ -1232,7 +1228,11 @@ declare global {
|
|
|
1232
1228
|
|
|
1233
1229
|
declare global {
|
|
1234
1230
|
interface HTMLElementTagNameMap {
|
|
1235
|
-
'gs-
|
|
1231
|
+
'gs-lineage-filter': LineageFilterComponent;
|
|
1232
|
+
}
|
|
1233
|
+
interface HTMLElementEventMap {
|
|
1234
|
+
[gsEventNames.lineageFilterChanged]: LineageFilterChangedEvent;
|
|
1235
|
+
[gsEventNames.lineageFilterMultiChanged]: LineageMultiFilterChangedEvent;
|
|
1236
1236
|
}
|
|
1237
1237
|
}
|
|
1238
1238
|
|
|
@@ -1240,7 +1240,7 @@ declare global {
|
|
|
1240
1240
|
declare global {
|
|
1241
1241
|
namespace JSX {
|
|
1242
1242
|
interface IntrinsicElements {
|
|
1243
|
-
'gs-
|
|
1243
|
+
'gs-lineage-filter': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
|
|
1244
1244
|
}
|
|
1245
1245
|
}
|
|
1246
1246
|
}
|
package/package.json
CHANGED
|
@@ -68,7 +68,7 @@ export function getFilteredMutationOverTimeData({
|
|
|
68
68
|
if (hideGaps) {
|
|
69
69
|
const dateRangesToFilterOut = filteredData.getSecondAxisKeys().filter((dateRange) => {
|
|
70
70
|
const vals = filteredData.getColumn(dateRange);
|
|
71
|
-
return !vals.some((v) => v?.type === 'value' && v.totalCount > 0);
|
|
71
|
+
return !vals.some((v) => (v?.type === 'value' || v?.type === 'valueWithCoverage') && v.totalCount > 0);
|
|
72
72
|
});
|
|
73
73
|
dateRangesToFilterOut.forEach((dateRange) => filteredData.deleteColumn(dateRange));
|
|
74
74
|
}
|
|
@@ -65,6 +65,53 @@ export const WithValue: StoryObj<MutationsOverTimeGridTooltipProps> = {
|
|
|
65
65
|
play: async ({ canvasElement }) => {
|
|
66
66
|
const canvas = within(canvasElement);
|
|
67
67
|
|
|
68
|
+
await expect(canvas.getByText('50.00%')).toBeVisible();
|
|
69
|
+
await expect(canvas.getByText('100')).toBeVisible();
|
|
70
|
+
await expect(canvas.getByText('have the mutation A500-.')).toBeVisible();
|
|
71
|
+
await expect(canvas.getByText('200')).toBeVisible();
|
|
72
|
+
await expect(canvas.getByText('have coverage at position 500.')).toBeVisible();
|
|
73
|
+
await expect(canvas.getByText('300')).toBeVisible();
|
|
74
|
+
await expect(canvas.getByText('total in this date range.')).toBeVisible();
|
|
75
|
+
},
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
export const WithValueWithZero: StoryObj<MutationsOverTimeGridTooltipProps> = {
|
|
79
|
+
...Template,
|
|
80
|
+
args: {
|
|
81
|
+
...Template.args,
|
|
82
|
+
value: {
|
|
83
|
+
type: 'value',
|
|
84
|
+
proportion: 0,
|
|
85
|
+
count: 0,
|
|
86
|
+
totalCount: 300,
|
|
87
|
+
},
|
|
88
|
+
},
|
|
89
|
+
play: async ({ canvasElement }) => {
|
|
90
|
+
const canvas = within(canvasElement);
|
|
91
|
+
|
|
92
|
+
await expect(canvas.getByText('0.00%')).toBeVisible();
|
|
93
|
+
await expect(canvas.getByText('0')).toBeVisible();
|
|
94
|
+
await expect(canvas.getByText('have the mutation A500-.')).toBeVisible();
|
|
95
|
+
await expect(canvas.queryByText('with coverage at position 500.')).not.toBeInTheDocument();
|
|
96
|
+
await expect(canvas.getByText('300')).toBeVisible();
|
|
97
|
+
await expect(canvas.getByText('total in this date range.')).toBeVisible();
|
|
98
|
+
},
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
export const WithValueWithCoverage: StoryObj<MutationsOverTimeGridTooltipProps> = {
|
|
102
|
+
...Template,
|
|
103
|
+
args: {
|
|
104
|
+
...Template.args,
|
|
105
|
+
value: {
|
|
106
|
+
type: 'valueWithCoverage',
|
|
107
|
+
count: 100,
|
|
108
|
+
coverage: 200,
|
|
109
|
+
totalCount: 300,
|
|
110
|
+
},
|
|
111
|
+
},
|
|
112
|
+
play: async ({ canvasElement }) => {
|
|
113
|
+
const canvas = within(canvasElement);
|
|
114
|
+
|
|
68
115
|
await expect(canvas.getByText('50.00%')).toBeVisible();
|
|
69
116
|
await expect(canvas.getByText('100')).toBeVisible();
|
|
70
117
|
await expect(canvas.getByText('have the mutation A500- out of')).toBeVisible();
|
|
@@ -21,12 +21,26 @@ export const MutationsOverTimeGridTooltip: FunctionComponent<MutationsOverTimeGr
|
|
|
21
21
|
}: MutationsOverTimeGridTooltipProps) => {
|
|
22
22
|
const dateClass = toTemporalClass(date);
|
|
23
23
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
24
|
+
let proportionText = 'No data';
|
|
25
|
+
|
|
26
|
+
if (value !== null) {
|
|
27
|
+
switch (value.type) {
|
|
28
|
+
case 'belowThreshold': {
|
|
29
|
+
proportionText = `<${formatProportion(MUTATIONS_OVER_TIME_MIN_PROPORTION)}`;
|
|
30
|
+
break;
|
|
31
|
+
}
|
|
32
|
+
case 'value':
|
|
33
|
+
case 'wastewaterValue': {
|
|
34
|
+
proportionText = formatProportion(value.proportion);
|
|
35
|
+
break;
|
|
36
|
+
}
|
|
37
|
+
case 'valueWithCoverage': {
|
|
38
|
+
// value.coverage will always be non-zero if we're in this case
|
|
39
|
+
proportionText = formatProportion(value.count / value.coverage);
|
|
40
|
+
break;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
30
44
|
|
|
31
45
|
return (
|
|
32
46
|
<div>
|
|
@@ -61,21 +75,50 @@ const TooltipValueCountsDescription: FunctionComponent<{
|
|
|
61
75
|
}
|
|
62
76
|
return (
|
|
63
77
|
<div className='mt-2'>
|
|
64
|
-
{
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
78
|
+
{(() => {
|
|
79
|
+
switch (value.type) {
|
|
80
|
+
case 'belowThreshold':
|
|
81
|
+
return (
|
|
82
|
+
<p className='text-gray-600'>
|
|
83
|
+
None or less than {formatProportion(MUTATIONS_OVER_TIME_MIN_PROPORTION)} have the
|
|
84
|
+
mutation.
|
|
85
|
+
</p>
|
|
86
|
+
);
|
|
87
|
+
|
|
88
|
+
case 'value':
|
|
89
|
+
return (
|
|
90
|
+
<>
|
|
91
|
+
<p>
|
|
92
|
+
{value.count}{' '}
|
|
93
|
+
<span className='text-gray-600'>have the mutation {mutationCode}.</span>
|
|
94
|
+
</p>
|
|
95
|
+
{value.proportion > 0 && (
|
|
96
|
+
<p>
|
|
97
|
+
{Math.round(value.count / value.proportion)}{' '}
|
|
98
|
+
<span className='text-gray-600'>
|
|
99
|
+
have coverage at position {mutationPosition}.
|
|
100
|
+
</span>
|
|
101
|
+
</p>
|
|
102
|
+
)}
|
|
103
|
+
</>
|
|
104
|
+
);
|
|
105
|
+
|
|
106
|
+
case 'valueWithCoverage':
|
|
107
|
+
return (
|
|
108
|
+
<>
|
|
109
|
+
<p>
|
|
110
|
+
{value.count}{' '}
|
|
111
|
+
<span className='text-gray-600'>have the mutation {mutationCode} out of</span>
|
|
112
|
+
</p>
|
|
113
|
+
<p>
|
|
114
|
+
{value.coverage}{' '}
|
|
115
|
+
<span className='text-gray-600'>with coverage at position {mutationPosition}.</span>
|
|
116
|
+
</p>
|
|
117
|
+
</>
|
|
118
|
+
);
|
|
119
|
+
}
|
|
120
|
+
})()}
|
|
121
|
+
|
|
79
122
|
<p>
|
|
80
123
|
{value.totalCount} <span className='text-gray-600'>total in this date range.</span>
|
|
81
124
|
</p>
|
|
@@ -83,13 +126,6 @@ const TooltipValueCountsDescription: FunctionComponent<{
|
|
|
83
126
|
);
|
|
84
127
|
};
|
|
85
128
|
|
|
86
|
-
function totalCountWithCoverage(count: number, proportion: number) {
|
|
87
|
-
if (count === 0) {
|
|
88
|
-
return 0;
|
|
89
|
-
}
|
|
90
|
-
return Math.round(count / proportion);
|
|
91
|
-
}
|
|
92
|
-
|
|
93
129
|
const timeIntervalDisplay = (date: TemporalClass) => {
|
|
94
130
|
if (date instanceof YearMonthDayClass) {
|
|
95
131
|
return date.toString();
|
|
@@ -4,7 +4,7 @@ import z from 'zod';
|
|
|
4
4
|
|
|
5
5
|
import { type MutationOverTimeDataMap } from './MutationOverTimeData';
|
|
6
6
|
import { MutationsOverTimeGridTooltip } from './mutations-over-time-grid-tooltip';
|
|
7
|
-
import { type MutationOverTimeMutationValue } from '../../query/queryMutationsOverTime';
|
|
7
|
+
import { getProportion, type MutationOverTimeMutationValue } from '../../query/queryMutationsOverTime';
|
|
8
8
|
import { type SequenceType } from '../../types';
|
|
9
9
|
import { type Deletion, type Substitution } from '../../utils/mutations';
|
|
10
10
|
import { type Temporal } from '../../utils/temporalClass';
|
|
@@ -211,7 +211,7 @@ const ProportionCell: FunctionComponent<{
|
|
|
211
211
|
colorScale: ColorScale;
|
|
212
212
|
tooltipPortalTarget: HTMLElement | null;
|
|
213
213
|
}> = ({ value, mutation, date, tooltipPosition, colorScale, tooltipPortalTarget }) => {
|
|
214
|
-
const proportion = value
|
|
214
|
+
const proportion = getProportion(value);
|
|
215
215
|
|
|
216
216
|
return (
|
|
217
217
|
<div className={'py-1 w-full h-full'}>
|
|
@@ -12,7 +12,7 @@ import {
|
|
|
12
12
|
} from './getFilteredMutationsOverTimeData';
|
|
13
13
|
import { type MutationOverTimeWorkerResponse } from './mutationOverTimeWorker';
|
|
14
14
|
import MutationsOverTimeGrid, { customColumnSchema } from './mutations-over-time-grid';
|
|
15
|
-
import { type MutationOverTimeQuery } from '../../query/queryMutationsOverTime';
|
|
15
|
+
import { getProportion, type MutationOverTimeQuery } from '../../query/queryMutationsOverTime';
|
|
16
16
|
import {
|
|
17
17
|
lapisFilterSchema,
|
|
18
18
|
sequenceTypeSchema,
|
|
@@ -356,7 +356,7 @@ function getDownloadData(filteredData: MutationOverTimeDataMap) {
|
|
|
356
356
|
return dates.reduce(
|
|
357
357
|
(accumulated, date) => {
|
|
358
358
|
const value = filteredData.get(mutation, date);
|
|
359
|
-
const proportion = value
|
|
359
|
+
const proportion = getProportion(value ?? null) ?? '';
|
|
360
360
|
return {
|
|
361
361
|
...accumulated,
|
|
362
362
|
[date.dateString]: proportion,
|
|
@@ -49,6 +49,12 @@ export type MutationOverTimeMutationValue =
|
|
|
49
49
|
count: number;
|
|
50
50
|
totalCount: number;
|
|
51
51
|
}
|
|
52
|
+
| {
|
|
53
|
+
type: 'valueWithCoverage';
|
|
54
|
+
count: number;
|
|
55
|
+
coverage: number;
|
|
56
|
+
totalCount: number;
|
|
57
|
+
}
|
|
52
58
|
| {
|
|
53
59
|
type: 'wastewaterValue';
|
|
54
60
|
proportion: number;
|
|
@@ -59,6 +65,19 @@ export type MutationOverTimeMutationValue =
|
|
|
59
65
|
}
|
|
60
66
|
| null;
|
|
61
67
|
|
|
68
|
+
export function getProportion(value: MutationOverTimeMutationValue) {
|
|
69
|
+
switch (value?.type) {
|
|
70
|
+
case 'value':
|
|
71
|
+
case 'wastewaterValue':
|
|
72
|
+
return value.proportion;
|
|
73
|
+
case 'valueWithCoverage':
|
|
74
|
+
return value.count / value.coverage;
|
|
75
|
+
case 'belowThreshold':
|
|
76
|
+
return undefined;
|
|
77
|
+
}
|
|
78
|
+
return undefined;
|
|
79
|
+
}
|
|
80
|
+
|
|
62
81
|
const MAX_NUMBER_OF_GRID_COLUMNS = 200;
|
|
63
82
|
export const MUTATIONS_OVER_TIME_MIN_PROPORTION = 0.001;
|
|
64
83
|
|
|
@@ -237,19 +256,6 @@ async function queryMutationsOverTimeDataDirectEndpoint(
|
|
|
237
256
|
}> {
|
|
238
257
|
const overallMutationData = await overallMutationDataPromise;
|
|
239
258
|
overallMutationData.sort((a, b) => sortSubstitutionsAndDeletions(a.mutation, b.mutation));
|
|
240
|
-
const totalCounts = await Promise.all(
|
|
241
|
-
allDates.map(async (date) => {
|
|
242
|
-
const filter = {
|
|
243
|
-
...lapisFilter,
|
|
244
|
-
[`${lapisDateField}From`]: date.firstDay.toString(),
|
|
245
|
-
[`${lapisDateField}To`]: date.lastDay.toString(),
|
|
246
|
-
};
|
|
247
|
-
|
|
248
|
-
const totalCountQuery = await getTotalNumberOfSequencesInDateRange(filter).evaluate(lapis, signal);
|
|
249
|
-
|
|
250
|
-
return totalCountQuery.content[0].count;
|
|
251
|
-
}),
|
|
252
|
-
);
|
|
253
259
|
|
|
254
260
|
const includeMutations = overallMutationData.map((value) => value.mutation.code);
|
|
255
261
|
const apiResult = await fetchMutationsOverTime(
|
|
@@ -267,6 +273,7 @@ async function queryMutationsOverTimeDataDirectEndpoint(
|
|
|
267
273
|
signal,
|
|
268
274
|
);
|
|
269
275
|
|
|
276
|
+
const totalCounts = apiResult.data.totalCountsByDateRange;
|
|
270
277
|
const responseMutations = apiResult.data.mutations.map(parseMutationCode);
|
|
271
278
|
const mutationEntries: SubstitutionOrDeletionEntry[] = responseMutations.map((mutation, i) => {
|
|
272
279
|
const numbers = {
|
|
@@ -316,9 +323,9 @@ async function queryMutationsOverTimeDataDirectEndpoint(
|
|
|
316
323
|
return [
|
|
317
324
|
date.dateString,
|
|
318
325
|
{
|
|
319
|
-
type: '
|
|
320
|
-
proportion: count / coverage,
|
|
326
|
+
type: 'valueWithCoverage',
|
|
321
327
|
count,
|
|
328
|
+
coverage,
|
|
322
329
|
totalCount,
|
|
323
330
|
},
|
|
324
331
|
];
|