@genspectrum/dashboard-components 1.6.0 → 1.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -0
- package/custom-elements.json +1 -1
- package/dist/{NumberRangeFilterChangedEvent-CQ32Qy8D.js → NumberRangeFilterChangedEvent-BnPI-Asz.js} +17 -3
- package/dist/NumberRangeFilterChangedEvent-BnPI-Asz.js.map +1 -0
- package/dist/assets/{mutationOverTimeWorker-BmB6BvVM.js.map → mutationOverTimeWorker-DPS3tmOd.js.map} +1 -1
- package/dist/components.d.ts +23 -23
- package/dist/components.js +97 -50
- package/dist/components.js.map +1 -1
- package/dist/util.d.ts +46 -22
- package/dist/util.js +2 -1
- package/package.json +1 -1
- package/src/preact/genomeViewer/CDSPlot.tsx +13 -2
- package/src/preact/genomeViewer/loadGff3.ts +6 -0
- package/src/preact/mutationFilter/mutation-filter.stories.tsx +2 -1
- package/src/preact/mutationFilter/mutation-filter.tsx +24 -27
- package/src/preact/mutationFilter/parseAndValidateMutation.ts +11 -11
- package/src/preact/mutationFilter/parseMutation.spec.ts +32 -22
- package/src/preact/mutationsOverTime/mutations-over-time.tsx +7 -4
- package/src/types.ts +17 -1
- package/src/utilEntrypoint.ts +4 -0
- package/src/utils/mutations.spec.ts +19 -0
- package/src/utils/mutations.ts +57 -10
- package/src/web-components/input/gs-mutation-filter.stories.ts +2 -1
- package/src/web-components/input/gs-mutation-filter.tsx +2 -6
- package/standalone-bundle/assets/{mutationOverTimeWorker-B_xP8pIC.js.map → mutationOverTimeWorker-Dp-A14AP.js.map} +1 -1
- package/standalone-bundle/dashboard-components.js +7103 -7062
- package/standalone-bundle/dashboard-components.js.map +1 -1
- package/dist/NumberRangeFilterChangedEvent-CQ32Qy8D.js.map +0 -1
package/dist/util.d.ts
CHANGED
|
@@ -194,6 +194,19 @@ declare const mapSourceSchema: default_2.ZodObject<{
|
|
|
194
194
|
topologyObjectsKey: string;
|
|
195
195
|
}>;
|
|
196
196
|
|
|
197
|
+
export declare type MeanProportionInterval = default_2.infer<typeof meanProportionIntervalSchema>;
|
|
198
|
+
|
|
199
|
+
declare const meanProportionIntervalSchema: default_2.ZodObject<{
|
|
200
|
+
min: default_2.ZodNumber;
|
|
201
|
+
max: default_2.ZodNumber;
|
|
202
|
+
}, "strip", default_2.ZodTypeAny, {
|
|
203
|
+
min: number;
|
|
204
|
+
max: number;
|
|
205
|
+
}, {
|
|
206
|
+
min: number;
|
|
207
|
+
max: number;
|
|
208
|
+
}>;
|
|
209
|
+
|
|
197
210
|
export declare type MutationAnnotation = default_2.infer<typeof mutationAnnotationSchema>;
|
|
198
211
|
|
|
199
212
|
export declare type MutationAnnotations = default_2.infer<typeof mutationAnnotationsSchema>;
|
|
@@ -430,6 +443,17 @@ export declare type MutationsView = default_2.infer<typeof mutationsViewSchema>;
|
|
|
430
443
|
|
|
431
444
|
declare const mutationsViewSchema: default_2.ZodUnion<[default_2.ZodLiteral<"table">, default_2.ZodLiteral<"grid">, default_2.ZodLiteral<"insertions">]>;
|
|
432
445
|
|
|
446
|
+
export declare type MutationType = default_2.infer<typeof mutationTypeSchema>;
|
|
447
|
+
|
|
448
|
+
export declare const mutationType: {
|
|
449
|
+
readonly nucleotideMutations: "nucleotideMutations";
|
|
450
|
+
readonly nucleotideInsertions: "nucleotideInsertions";
|
|
451
|
+
readonly aminoAcidMutations: "aminoAcidMutations";
|
|
452
|
+
readonly aminoAcidInsertions: "aminoAcidInsertions";
|
|
453
|
+
};
|
|
454
|
+
|
|
455
|
+
declare const mutationTypeSchema: default_2.ZodEnum<["nucleotideMutations", "nucleotideInsertions", "aminoAcidMutations", "aminoAcidInsertions"]>;
|
|
456
|
+
|
|
433
457
|
export declare type NamedLapisFilter = default_2.infer<typeof namedLapisFilterSchema>;
|
|
434
458
|
|
|
435
459
|
declare const namedLapisFilterSchema: default_2.ZodObject<{
|
|
@@ -917,7 +941,7 @@ declare global {
|
|
|
917
941
|
|
|
918
942
|
declare global {
|
|
919
943
|
interface HTMLElementTagNameMap {
|
|
920
|
-
'gs-
|
|
944
|
+
'gs-genome-data-viewer': GenomeDataViewerComponent;
|
|
921
945
|
}
|
|
922
946
|
}
|
|
923
947
|
|
|
@@ -925,7 +949,7 @@ declare global {
|
|
|
925
949
|
declare global {
|
|
926
950
|
namespace JSX {
|
|
927
951
|
interface IntrinsicElements {
|
|
928
|
-
'gs-
|
|
952
|
+
'gs-genome-data-viewer': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
|
|
929
953
|
}
|
|
930
954
|
}
|
|
931
955
|
}
|
|
@@ -947,22 +971,6 @@ declare global {
|
|
|
947
971
|
}
|
|
948
972
|
|
|
949
973
|
|
|
950
|
-
declare global {
|
|
951
|
-
interface HTMLElementTagNameMap {
|
|
952
|
-
'gs-genome-data-viewer': GenomeDataViewerComponent;
|
|
953
|
-
}
|
|
954
|
-
}
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
declare global {
|
|
958
|
-
namespace JSX {
|
|
959
|
-
interface IntrinsicElements {
|
|
960
|
-
'gs-genome-data-viewer': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
|
|
961
|
-
}
|
|
962
|
-
}
|
|
963
|
-
}
|
|
964
|
-
|
|
965
|
-
|
|
966
974
|
declare global {
|
|
967
975
|
interface HTMLElementTagNameMap {
|
|
968
976
|
'gs-mutations': MutationsComponent;
|
|
@@ -981,7 +989,7 @@ declare global {
|
|
|
981
989
|
|
|
982
990
|
declare global {
|
|
983
991
|
interface HTMLElementTagNameMap {
|
|
984
|
-
'gs-
|
|
992
|
+
'gs-relative-growth-advantage': RelativeGrowthAdvantageComponent;
|
|
985
993
|
}
|
|
986
994
|
}
|
|
987
995
|
|
|
@@ -989,7 +997,7 @@ declare global {
|
|
|
989
997
|
declare global {
|
|
990
998
|
namespace JSX {
|
|
991
999
|
interface IntrinsicElements {
|
|
992
|
-
'gs-
|
|
1000
|
+
'gs-relative-growth-advantage': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
|
|
993
1001
|
}
|
|
994
1002
|
}
|
|
995
1003
|
}
|
|
@@ -997,7 +1005,7 @@ declare global {
|
|
|
997
1005
|
|
|
998
1006
|
declare global {
|
|
999
1007
|
interface HTMLElementTagNameMap {
|
|
1000
|
-
'gs-
|
|
1008
|
+
'gs-prevalence-over-time': PrevalenceOverTimeComponent;
|
|
1001
1009
|
}
|
|
1002
1010
|
}
|
|
1003
1011
|
|
|
@@ -1005,7 +1013,7 @@ declare global {
|
|
|
1005
1013
|
declare global {
|
|
1006
1014
|
namespace JSX {
|
|
1007
1015
|
interface IntrinsicElements {
|
|
1008
|
-
'gs-
|
|
1016
|
+
'gs-prevalence-over-time': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
|
|
1009
1017
|
}
|
|
1010
1018
|
}
|
|
1011
1019
|
}
|
|
@@ -1207,6 +1215,22 @@ declare global {
|
|
|
1207
1215
|
}
|
|
1208
1216
|
|
|
1209
1217
|
|
|
1218
|
+
declare global {
|
|
1219
|
+
interface HTMLElementTagNameMap {
|
|
1220
|
+
'gs-wastewater-mutations-over-time': WastewaterMutationsOverTimeComponent;
|
|
1221
|
+
}
|
|
1222
|
+
}
|
|
1223
|
+
|
|
1224
|
+
|
|
1225
|
+
declare global {
|
|
1226
|
+
namespace JSX {
|
|
1227
|
+
interface IntrinsicElements {
|
|
1228
|
+
'gs-wastewater-mutations-over-time': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
|
|
1229
|
+
}
|
|
1230
|
+
}
|
|
1231
|
+
}
|
|
1232
|
+
|
|
1233
|
+
|
|
1210
1234
|
declare module 'chart.js' {
|
|
1211
1235
|
interface CartesianScaleTypeRegistry {
|
|
1212
1236
|
logit: {
|
package/dist/util.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { D, a, L, N, b, T, d, g, v } from "./NumberRangeFilterChangedEvent-
|
|
1
|
+
import { D, a, L, N, b, T, d, g, m, v } from "./NumberRangeFilterChangedEvent-BnPI-Asz.js";
|
|
2
2
|
export {
|
|
3
3
|
D as DateRangeOptionChangedEvent,
|
|
4
4
|
a as LineageFilterChangedEvent,
|
|
@@ -8,6 +8,7 @@ export {
|
|
|
8
8
|
T as TextFilterChangedEvent,
|
|
9
9
|
d as dateRangeOptionPresets,
|
|
10
10
|
g as gsEventNames,
|
|
11
|
+
m as mutationType,
|
|
11
12
|
v as views
|
|
12
13
|
};
|
|
13
14
|
//# sourceMappingURL=util.js.map
|
package/package.json
CHANGED
|
@@ -20,9 +20,16 @@ function getMaxTickNumber(fullWidth: number): number {
|
|
|
20
20
|
}
|
|
21
21
|
|
|
22
22
|
function getTicks(zoomStart: number, zoomEnd: number, fullWidth: number) {
|
|
23
|
-
|
|
23
|
+
let maxTickNumber = getMaxTickNumber(fullWidth);
|
|
24
24
|
const length = zoomEnd - zoomStart;
|
|
25
|
-
|
|
25
|
+
let minTickSize = length / maxTickNumber;
|
|
26
|
+
if (minTickSize <= 1) {
|
|
27
|
+
maxTickNumber = MIN_TICK_NUMBER;
|
|
28
|
+
minTickSize = length / maxTickNumber;
|
|
29
|
+
}
|
|
30
|
+
if (minTickSize <= 1) {
|
|
31
|
+
return [];
|
|
32
|
+
}
|
|
26
33
|
let maxTickSize = 10 ** Math.round(Math.log(minTickSize) / Math.log(10));
|
|
27
34
|
const numTicks = Math.round(length / maxTickSize);
|
|
28
35
|
if (numTicks > maxTickNumber) {
|
|
@@ -78,6 +85,7 @@ const XAxis: FunctionComponent<XAxisProps> = (componentProps) => {
|
|
|
78
85
|
width: `calc(${widthPercent}% - 1px)`,
|
|
79
86
|
}}
|
|
80
87
|
>
|
|
88
|
+
{/* TODO(#994): determine if text can be shown based on text width */}
|
|
81
89
|
{width >= averageWidth ? tick.start : ''}
|
|
82
90
|
</div>
|
|
83
91
|
);
|
|
@@ -142,6 +150,9 @@ const CDSBars: FunctionComponent<CDSBarsProps> = (componentProps) => {
|
|
|
142
150
|
if (start >= end) {
|
|
143
151
|
return null;
|
|
144
152
|
}
|
|
153
|
+
if (zoomEnd - zoomStart <= 2) {
|
|
154
|
+
return null;
|
|
155
|
+
}
|
|
145
156
|
|
|
146
157
|
const widthPercent = ((end - start) / visibleRegionLength) * 100;
|
|
147
158
|
const leftPercent = ((start - zoomStart) / visibleRegionLength) * 100;
|
|
@@ -22,6 +22,12 @@ export async function loadGff3(gff3Source: string, genomeLength: number | undefi
|
|
|
22
22
|
}
|
|
23
23
|
|
|
24
24
|
const response = await fetch(gff3Source);
|
|
25
|
+
if (!response.ok) {
|
|
26
|
+
throw new UserFacingError(
|
|
27
|
+
'GFF3 download failed',
|
|
28
|
+
`Server returned ${response.status} ${response.statusText} for ${response.url}`,
|
|
29
|
+
);
|
|
30
|
+
}
|
|
25
31
|
const content = await response.text();
|
|
26
32
|
genomeLength ??= loadGenomeLength(content);
|
|
27
33
|
return { features: parseGFF3(content), length: genomeLength };
|
|
@@ -6,6 +6,7 @@ import { MutationFilter, type MutationFilterProps } from './mutation-filter';
|
|
|
6
6
|
import { previewHandles } from '../../../.storybook/preview';
|
|
7
7
|
import { LAPIS_URL } from '../../constants';
|
|
8
8
|
import referenceGenome from '../../lapisApi/__mockData__/referenceGenome.json';
|
|
9
|
+
import { mutationType } from '../../types';
|
|
9
10
|
import { gsEventNames } from '../../utils/gsEventNames';
|
|
10
11
|
import { LapisUrlContextProvider } from '../LapisUrlContext';
|
|
11
12
|
import { ReferenceGenomeContext } from '../ReferenceGenomeContext';
|
|
@@ -230,7 +231,7 @@ export const FiltersOutDisabledMutationTypes: StoryObj<MutationFilterProps> = {
|
|
|
230
231
|
...Default,
|
|
231
232
|
args: {
|
|
232
233
|
...Default.args,
|
|
233
|
-
enabledMutationTypes: [
|
|
234
|
+
enabledMutationTypes: [mutationType.nucleotideMutations],
|
|
234
235
|
},
|
|
235
236
|
play: async ({ canvasElement, step }) => {
|
|
236
237
|
const { canvas, changedListenerMock } = await prepare(canvasElement, step);
|
|
@@ -7,7 +7,13 @@ import { getExampleMutation } from './ExampleMutation';
|
|
|
7
7
|
import { MutationFilterInfo } from './mutation-filter-info';
|
|
8
8
|
import { parseAndValidateMutation } from './parseAndValidateMutation';
|
|
9
9
|
import { type ReferenceGenome } from '../../lapisApi/ReferenceGenome';
|
|
10
|
-
import {
|
|
10
|
+
import {
|
|
11
|
+
type MutationsFilter,
|
|
12
|
+
mutationsFilterSchema,
|
|
13
|
+
mutationType,
|
|
14
|
+
mutationTypeSchema,
|
|
15
|
+
type MutationType,
|
|
16
|
+
} from '../../types';
|
|
11
17
|
import { gsEventNames } from '../../utils/gsEventNames';
|
|
12
18
|
import { type DeletionClass, type InsertionClass, type SubstitutionClass } from '../../utils/mutations';
|
|
13
19
|
import { ReferenceGenomeContext } from '../ReferenceGenomeContext';
|
|
@@ -15,15 +21,6 @@ import { ErrorBoundary } from '../components/error-boundary';
|
|
|
15
21
|
import { UserFacingError } from '../components/error-display';
|
|
16
22
|
import { singleGraphColorRGBByName } from '../shared/charts/colors';
|
|
17
23
|
|
|
18
|
-
const mutationTypeSchema = z.enum([
|
|
19
|
-
'nucleotideMutations',
|
|
20
|
-
'aminoAcidMutations',
|
|
21
|
-
'nucleotideInsertions',
|
|
22
|
-
'aminoAcidInsertions',
|
|
23
|
-
]);
|
|
24
|
-
|
|
25
|
-
export type MutationType = z.infer<typeof mutationTypeSchema>;
|
|
26
|
-
|
|
27
24
|
const mutationFilterInnerPropsSchema = z.object({
|
|
28
25
|
initialValue: z.union([mutationsFilterSchema.optional(), z.array(z.string()), z.undefined()]),
|
|
29
26
|
enabledMutationTypes: z.array(mutationTypeSchema).optional(),
|
|
@@ -37,22 +34,22 @@ export type MutationFilterInnerProps = z.infer<typeof mutationFilterInnerPropsSc
|
|
|
37
34
|
export type MutationFilterProps = z.infer<typeof mutationFilterPropsSchema>;
|
|
38
35
|
|
|
39
36
|
type SelectedNucleotideMutation = {
|
|
40
|
-
type:
|
|
37
|
+
type: typeof mutationType.nucleotideMutations;
|
|
41
38
|
value: SubstitutionClass | DeletionClass;
|
|
42
39
|
};
|
|
43
40
|
|
|
44
41
|
type SelectedAminoAcidMutation = {
|
|
45
|
-
type:
|
|
42
|
+
type: typeof mutationType.aminoAcidMutations;
|
|
46
43
|
value: SubstitutionClass | DeletionClass;
|
|
47
44
|
};
|
|
48
45
|
|
|
49
46
|
type SelectedNucleotideInsertion = {
|
|
50
|
-
type:
|
|
47
|
+
type: typeof mutationType.nucleotideInsertions;
|
|
51
48
|
value: InsertionClass;
|
|
52
49
|
};
|
|
53
50
|
|
|
54
51
|
type SelectedAminoAcidInsertion = {
|
|
55
|
-
type:
|
|
52
|
+
type: typeof mutationType.aminoAcidInsertions;
|
|
56
53
|
value: InsertionClass;
|
|
57
54
|
};
|
|
58
55
|
|
|
@@ -80,7 +77,7 @@ export const MutationFilter: FunctionComponent<MutationFilterProps> = (props) =>
|
|
|
80
77
|
|
|
81
78
|
function MutationFilterInner({
|
|
82
79
|
initialValue,
|
|
83
|
-
enabledMutationTypes =
|
|
80
|
+
enabledMutationTypes = Object.values(mutationType),
|
|
84
81
|
}: MutationFilterInnerProps) {
|
|
85
82
|
const referenceGenome = useContext(ReferenceGenomeContext);
|
|
86
83
|
const filterRef = useRef<HTMLDivElement>(null);
|
|
@@ -309,16 +306,16 @@ function getInitialState(
|
|
|
309
306
|
function getPlaceholder(referenceGenome: ReferenceGenome, enabledMutationTypes: MutationType[]) {
|
|
310
307
|
const exampleMutationList = [];
|
|
311
308
|
|
|
312
|
-
if (enabledMutationTypes.includes(
|
|
309
|
+
if (enabledMutationTypes.includes(mutationType.nucleotideMutations)) {
|
|
313
310
|
exampleMutationList.push(getExampleMutation(referenceGenome, 'nucleotide', 'substitution'));
|
|
314
311
|
}
|
|
315
|
-
if (enabledMutationTypes.includes(
|
|
312
|
+
if (enabledMutationTypes.includes(mutationType.nucleotideInsertions)) {
|
|
316
313
|
exampleMutationList.push(getExampleMutation(referenceGenome, 'nucleotide', 'insertion'));
|
|
317
314
|
}
|
|
318
|
-
if (enabledMutationTypes.includes(
|
|
315
|
+
if (enabledMutationTypes.includes(mutationType.aminoAcidMutations)) {
|
|
319
316
|
exampleMutationList.push(getExampleMutation(referenceGenome, 'amino acid', 'substitution'));
|
|
320
317
|
}
|
|
321
|
-
if (enabledMutationTypes.includes(
|
|
318
|
+
if (enabledMutationTypes.includes(mutationType.aminoAcidInsertions)) {
|
|
322
319
|
exampleMutationList.push(getExampleMutation(referenceGenome, 'amino acid', 'insertion'));
|
|
323
320
|
}
|
|
324
321
|
|
|
@@ -329,13 +326,13 @@ function getPlaceholder(referenceGenome: ReferenceGenome, enabledMutationTypes:
|
|
|
329
326
|
|
|
330
327
|
const backgroundColorMap = (data: MutationFilterItem, alpha: number = 0.4) => {
|
|
331
328
|
switch (data.type) {
|
|
332
|
-
case
|
|
329
|
+
case mutationType.nucleotideMutations:
|
|
333
330
|
return singleGraphColorRGBByName('green', alpha);
|
|
334
|
-
case
|
|
331
|
+
case mutationType.aminoAcidMutations:
|
|
335
332
|
return singleGraphColorRGBByName('teal', alpha);
|
|
336
|
-
case
|
|
333
|
+
case mutationType.nucleotideInsertions:
|
|
337
334
|
return singleGraphColorRGBByName('indigo', alpha);
|
|
338
|
-
case
|
|
335
|
+
case mutationType.aminoAcidInsertions:
|
|
339
336
|
return singleGraphColorRGBByName('purple', alpha);
|
|
340
337
|
}
|
|
341
338
|
};
|
|
@@ -370,13 +367,13 @@ function mapToMutationFilterStrings(selectedFilters: MutationFilterItem[]) {
|
|
|
370
367
|
return selectedFilters.reduce<MutationsFilter>(
|
|
371
368
|
(acc, filter) => {
|
|
372
369
|
switch (filter.type) {
|
|
373
|
-
case
|
|
370
|
+
case mutationType.nucleotideMutations:
|
|
374
371
|
return { ...acc, nucleotideMutations: [...acc.nucleotideMutations, filter.value.toString()] };
|
|
375
|
-
case
|
|
372
|
+
case mutationType.aminoAcidMutations:
|
|
376
373
|
return { ...acc, aminoAcidMutations: [...acc.aminoAcidMutations, filter.value.toString()] };
|
|
377
|
-
case
|
|
374
|
+
case mutationType.nucleotideInsertions:
|
|
378
375
|
return { ...acc, nucleotideInsertions: [...acc.nucleotideInsertions, filter.value.toString()] };
|
|
379
|
-
case
|
|
376
|
+
case mutationType.aminoAcidInsertions:
|
|
380
377
|
return { ...acc, aminoAcidInsertions: [...acc.aminoAcidInsertions, filter.value.toString()] };
|
|
381
378
|
}
|
|
382
379
|
},
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { type MutationFilterItem } from './mutation-filter';
|
|
2
2
|
import { sequenceTypeFromSegment } from './sequenceTypeFromSegment';
|
|
3
3
|
import type { ReferenceGenome } from '../../lapisApi/ReferenceGenome';
|
|
4
|
-
import type
|
|
4
|
+
import { type SequenceType, mutationType } from '../../types';
|
|
5
5
|
import { DeletionClass, InsertionClass, type Mutation, SubstitutionClass } from '../../utils/mutations';
|
|
6
6
|
|
|
7
7
|
export const parseAndValidateMutation = (
|
|
@@ -22,11 +22,11 @@ export const parseAndValidateMutation = (
|
|
|
22
22
|
|
|
23
23
|
const getSequenceType = (type: MutationFilterItem['type']) => {
|
|
24
24
|
switch (type) {
|
|
25
|
-
case
|
|
26
|
-
case
|
|
25
|
+
case mutationType.nucleotideInsertions:
|
|
26
|
+
case mutationType.nucleotideMutations:
|
|
27
27
|
return 'nucleotide';
|
|
28
|
-
case
|
|
29
|
-
case
|
|
28
|
+
case mutationType.aminoAcidInsertions:
|
|
29
|
+
case mutationType.aminoAcidMutations:
|
|
30
30
|
return 'amino acid';
|
|
31
31
|
}
|
|
32
32
|
};
|
|
@@ -37,10 +37,10 @@ const parseMutation = (value: string, referenceGenome: ReferenceGenome): Mutatio
|
|
|
37
37
|
const sequenceType = sequenceTypeFromSegment(possibleInsertion.segment, referenceGenome);
|
|
38
38
|
switch (sequenceType) {
|
|
39
39
|
case 'nucleotide': {
|
|
40
|
-
return { type:
|
|
40
|
+
return { type: mutationType.nucleotideInsertions, value: possibleInsertion };
|
|
41
41
|
}
|
|
42
42
|
case 'amino acid':
|
|
43
|
-
return { type:
|
|
43
|
+
return { type: mutationType.aminoAcidInsertions, value: possibleInsertion };
|
|
44
44
|
case undefined:
|
|
45
45
|
return null;
|
|
46
46
|
}
|
|
@@ -51,9 +51,9 @@ const parseMutation = (value: string, referenceGenome: ReferenceGenome): Mutatio
|
|
|
51
51
|
const sequenceType = sequenceTypeFromSegment(possibleDeletion.segment, referenceGenome);
|
|
52
52
|
switch (sequenceType) {
|
|
53
53
|
case 'nucleotide':
|
|
54
|
-
return { type:
|
|
54
|
+
return { type: mutationType.nucleotideMutations, value: possibleDeletion };
|
|
55
55
|
case 'amino acid':
|
|
56
|
-
return { type:
|
|
56
|
+
return { type: mutationType.aminoAcidMutations, value: possibleDeletion };
|
|
57
57
|
case undefined:
|
|
58
58
|
return null;
|
|
59
59
|
}
|
|
@@ -64,10 +64,10 @@ const parseMutation = (value: string, referenceGenome: ReferenceGenome): Mutatio
|
|
|
64
64
|
const sequenceType = sequenceTypeFromSegment(possibleSubstitution.segment, referenceGenome);
|
|
65
65
|
switch (sequenceType) {
|
|
66
66
|
case 'nucleotide': {
|
|
67
|
-
return { type:
|
|
67
|
+
return { type: mutationType.nucleotideMutations, value: possibleSubstitution };
|
|
68
68
|
}
|
|
69
69
|
case 'amino acid': {
|
|
70
|
-
return { type:
|
|
70
|
+
return { type: mutationType.aminoAcidMutations, value: possibleSubstitution };
|
|
71
71
|
}
|
|
72
72
|
|
|
73
73
|
case undefined:
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { describe, expect, it } from 'vitest';
|
|
2
2
|
|
|
3
3
|
import { parseAndValidateMutation } from './parseAndValidateMutation';
|
|
4
|
+
import { mutationType } from '../../types';
|
|
4
5
|
import { DeletionClass, InsertionClass, SubstitutionClass } from '../../utils/mutations';
|
|
5
6
|
|
|
6
7
|
describe('parseMutation', () => {
|
|
@@ -28,32 +29,32 @@ describe('parseMutation', () => {
|
|
|
28
29
|
{
|
|
29
30
|
name: 'should parse nucleotide insertions',
|
|
30
31
|
input: 'ins_3:ACGT',
|
|
31
|
-
expected: { type:
|
|
32
|
+
expected: { type: mutationType.nucleotideInsertions, value: new InsertionClass(undefined, 3, 'ACGT') },
|
|
32
33
|
},
|
|
33
34
|
{
|
|
34
35
|
name: 'should parse amino acid insertions',
|
|
35
36
|
input: 'ins_gene1:3:ACGT',
|
|
36
|
-
expected: { type:
|
|
37
|
+
expected: { type: mutationType.aminoAcidInsertions, value: new InsertionClass('gene1', 3, 'ACGT') },
|
|
37
38
|
},
|
|
38
39
|
{
|
|
39
40
|
name: 'should parse amino acid insertions in all upper case',
|
|
40
41
|
input: 'INS_GENE1:3:ACGT',
|
|
41
|
-
expected: { type:
|
|
42
|
+
expected: { type: mutationType.aminoAcidInsertions, value: new InsertionClass('GENE1', 3, 'ACGT') },
|
|
42
43
|
},
|
|
43
44
|
{
|
|
44
45
|
name: 'should parse amino acid insertions in all lower case',
|
|
45
46
|
input: 'ins_gene1:3:acgt',
|
|
46
|
-
expected: { type:
|
|
47
|
+
expected: { type: mutationType.aminoAcidInsertions, value: new InsertionClass('gene1', 3, 'acgt') },
|
|
47
48
|
},
|
|
48
49
|
{
|
|
49
50
|
name: 'should parse amino acid insertion with LAPIS-style wildcard',
|
|
50
51
|
input: 'ins_gene1:3:?AC?GT',
|
|
51
|
-
expected: { type:
|
|
52
|
+
expected: { type: mutationType.aminoAcidInsertions, value: new InsertionClass('gene1', 3, '?AC?GT') },
|
|
52
53
|
},
|
|
53
54
|
{
|
|
54
55
|
name: 'should parse amino acid insertion with SILO-style wildcard',
|
|
55
56
|
input: 'ins_gene1:3:.*AC.*GT',
|
|
56
|
-
expected: { type:
|
|
57
|
+
expected: { type: mutationType.aminoAcidInsertions, value: new InsertionClass('gene1', 3, '.*AC.*GT') },
|
|
57
58
|
},
|
|
58
59
|
{
|
|
59
60
|
name: 'should return null for insertion with segment not in reference genome',
|
|
@@ -71,42 +72,42 @@ describe('parseMutation', () => {
|
|
|
71
72
|
{
|
|
72
73
|
name: 'should parse nucleotide deletion in single segmented reference genome, when no segment is given',
|
|
73
74
|
input: 'A3-',
|
|
74
|
-
expected: { type:
|
|
75
|
+
expected: { type: mutationType.nucleotideMutations, value: new DeletionClass(undefined, 'A', 3) },
|
|
75
76
|
},
|
|
76
77
|
{
|
|
77
78
|
name: 'should parse nucleotide deletion without valueAtReference when no segment is given',
|
|
78
79
|
input: '3-',
|
|
79
|
-
expected: { type:
|
|
80
|
+
expected: { type: mutationType.nucleotideMutations, value: new DeletionClass(undefined, undefined, 3) },
|
|
80
81
|
},
|
|
81
82
|
{
|
|
82
83
|
name: 'should parse nucleotide deletion',
|
|
83
84
|
input: 'nuc1:A3-',
|
|
84
|
-
expected: { type:
|
|
85
|
+
expected: { type: mutationType.nucleotideMutations, value: new DeletionClass('nuc1', 'A', 3) },
|
|
85
86
|
},
|
|
86
87
|
{
|
|
87
88
|
name: 'should parse nucleotide deletion without valueAtReference',
|
|
88
89
|
input: 'nuc1:3-',
|
|
89
|
-
expected: { type:
|
|
90
|
+
expected: { type: mutationType.nucleotideMutations, value: new DeletionClass('nuc1', undefined, 3) },
|
|
90
91
|
},
|
|
91
92
|
{
|
|
92
93
|
name: 'should parse amino acid deletion',
|
|
93
94
|
input: 'gene1:A3-',
|
|
94
|
-
expected: { type:
|
|
95
|
+
expected: { type: mutationType.aminoAcidMutations, value: new DeletionClass('gene1', 'A', 3) },
|
|
95
96
|
},
|
|
96
97
|
{
|
|
97
98
|
name: 'should parse amino acid deletion in all upper case',
|
|
98
99
|
input: 'GENE1:A3-',
|
|
99
|
-
expected: { type:
|
|
100
|
+
expected: { type: mutationType.aminoAcidMutations, value: new DeletionClass('GENE1', 'A', 3) },
|
|
100
101
|
},
|
|
101
102
|
{
|
|
102
103
|
name: 'should parse amino acid deletion in all lower case',
|
|
103
104
|
input: 'gene1:a3-',
|
|
104
|
-
expected: { type:
|
|
105
|
+
expected: { type: mutationType.aminoAcidMutations, value: new DeletionClass('gene1', 'a', 3) },
|
|
105
106
|
},
|
|
106
107
|
{
|
|
107
108
|
name: 'should parse amino acid deletion without valueAtReference',
|
|
108
109
|
input: 'gene1:3-',
|
|
109
|
-
expected: { type:
|
|
110
|
+
expected: { type: mutationType.aminoAcidMutations, value: new DeletionClass('gene1', undefined, 3) },
|
|
110
111
|
},
|
|
111
112
|
{
|
|
112
113
|
name: 'should return null for deletion with segment not in reference genome',
|
|
@@ -123,45 +124,54 @@ describe('parseMutation', () => {
|
|
|
123
124
|
{
|
|
124
125
|
name: 'should parse nucleotide substitution in single segmented reference genome, when no segment is given',
|
|
125
126
|
input: 'A3T',
|
|
126
|
-
expected: {
|
|
127
|
+
expected: {
|
|
128
|
+
type: mutationType.nucleotideMutations,
|
|
129
|
+
value: new SubstitutionClass(undefined, 'A', 'T', 3),
|
|
130
|
+
},
|
|
127
131
|
},
|
|
128
132
|
{
|
|
129
133
|
name: 'should parse substitution without valueAtReference',
|
|
130
134
|
input: '3T',
|
|
131
|
-
expected: {
|
|
135
|
+
expected: {
|
|
136
|
+
type: mutationType.nucleotideMutations,
|
|
137
|
+
value: new SubstitutionClass(undefined, undefined, 'T', 3),
|
|
138
|
+
},
|
|
132
139
|
},
|
|
133
140
|
{
|
|
134
141
|
name: 'should parse substitution with neither valueAtReference not substitutionValue',
|
|
135
142
|
input: '3',
|
|
136
143
|
expected: {
|
|
137
|
-
type:
|
|
144
|
+
type: mutationType.nucleotideMutations,
|
|
138
145
|
value: new SubstitutionClass(undefined, undefined, undefined, 3),
|
|
139
146
|
},
|
|
140
147
|
},
|
|
141
148
|
{
|
|
142
149
|
name: 'should parse a "no mutation" substitution',
|
|
143
150
|
input: '3.',
|
|
144
|
-
expected: {
|
|
151
|
+
expected: {
|
|
152
|
+
type: mutationType.nucleotideMutations,
|
|
153
|
+
value: new SubstitutionClass(undefined, undefined, '.', 3),
|
|
154
|
+
},
|
|
145
155
|
},
|
|
146
156
|
{
|
|
147
157
|
name: 'should parse nucleotide substitution',
|
|
148
158
|
input: 'nuc1:A3T',
|
|
149
|
-
expected: { type:
|
|
159
|
+
expected: { type: mutationType.nucleotideMutations, value: new SubstitutionClass('nuc1', 'A', 'T', 3) },
|
|
150
160
|
},
|
|
151
161
|
{
|
|
152
162
|
name: 'should parse amino acid substitution',
|
|
153
163
|
input: 'gene1:A3T',
|
|
154
|
-
expected: { type:
|
|
164
|
+
expected: { type: mutationType.aminoAcidMutations, value: new SubstitutionClass('gene1', 'A', 'T', 3) },
|
|
155
165
|
},
|
|
156
166
|
{
|
|
157
167
|
name: 'should parse amino acid substitution in all upper case',
|
|
158
168
|
input: 'GENE1:A3T',
|
|
159
|
-
expected: { type:
|
|
169
|
+
expected: { type: mutationType.aminoAcidMutations, value: new SubstitutionClass('GENE1', 'A', 'T', 3) },
|
|
160
170
|
},
|
|
161
171
|
{
|
|
162
172
|
name: 'should parse amino acid substitution in all lower case',
|
|
163
173
|
input: 'gene1:a3t',
|
|
164
|
-
expected: { type:
|
|
174
|
+
expected: { type: mutationType.aminoAcidMutations, value: new SubstitutionClass('gene1', 'a', 't', 3) },
|
|
165
175
|
},
|
|
166
176
|
{
|
|
167
177
|
name: 'should return null for substitution with segment not in reference genome',
|
|
@@ -47,6 +47,12 @@ import { useWebWorker } from '../webWorkers/useWebWorker';
|
|
|
47
47
|
const mutationsOverTimeViewSchema = z.literal(views.grid);
|
|
48
48
|
export type MutationsOverTimeView = z.infer<typeof mutationsOverTimeViewSchema>;
|
|
49
49
|
|
|
50
|
+
const meanProportionIntervalSchema = z.object({
|
|
51
|
+
min: z.number().min(0).max(1),
|
|
52
|
+
max: z.number().min(0).max(1),
|
|
53
|
+
});
|
|
54
|
+
export type MeanProportionInterval = z.infer<typeof meanProportionIntervalSchema>;
|
|
55
|
+
|
|
50
56
|
const mutationOverTimeSchema = z.object({
|
|
51
57
|
lapisFilter: lapisFilterSchema,
|
|
52
58
|
sequenceType: sequenceTypeSchema,
|
|
@@ -55,10 +61,7 @@ const mutationOverTimeSchema = z.object({
|
|
|
55
61
|
lapisDateField: z.string().min(1),
|
|
56
62
|
useNewEndpoint: z.boolean().optional(),
|
|
57
63
|
displayMutations: displayMutationsSchema.optional(),
|
|
58
|
-
initialMeanProportionInterval:
|
|
59
|
-
min: z.number().min(0).max(1),
|
|
60
|
-
max: z.number().min(0).max(1),
|
|
61
|
-
}),
|
|
64
|
+
initialMeanProportionInterval: meanProportionIntervalSchema,
|
|
62
65
|
hideGaps: z.boolean().optional(),
|
|
63
66
|
width: z.string(),
|
|
64
67
|
height: z.string().optional(),
|
package/src/types.ts
CHANGED
|
@@ -44,7 +44,7 @@ export type SequenceType = z.infer<typeof sequenceTypeSchema>;
|
|
|
44
44
|
|
|
45
45
|
export type SubstitutionOrDeletion = 'substitution' | 'deletion';
|
|
46
46
|
|
|
47
|
-
export type
|
|
47
|
+
export type SubstitutionOrDeletionOrInsertion = SubstitutionOrDeletion | 'insertion';
|
|
48
48
|
|
|
49
49
|
export type SubstitutionEntry<T extends Substitution = SubstitutionClass> = {
|
|
50
50
|
type: 'substitution';
|
|
@@ -79,3 +79,19 @@ export const views = {
|
|
|
79
79
|
bubble: 'bubble',
|
|
80
80
|
map: 'map',
|
|
81
81
|
} as const;
|
|
82
|
+
|
|
83
|
+
export const mutationType = {
|
|
84
|
+
nucleotideMutations: 'nucleotideMutations',
|
|
85
|
+
nucleotideInsertions: 'nucleotideInsertions',
|
|
86
|
+
aminoAcidMutations: 'aminoAcidMutations',
|
|
87
|
+
aminoAcidInsertions: 'aminoAcidInsertions',
|
|
88
|
+
} as const;
|
|
89
|
+
|
|
90
|
+
export const mutationTypeSchema = z.enum([
|
|
91
|
+
mutationType.nucleotideMutations,
|
|
92
|
+
mutationType.nucleotideInsertions,
|
|
93
|
+
mutationType.aminoAcidMutations,
|
|
94
|
+
mutationType.aminoAcidInsertions,
|
|
95
|
+
]);
|
|
96
|
+
|
|
97
|
+
export type MutationType = z.infer<typeof mutationTypeSchema>;
|
package/src/utilEntrypoint.ts
CHANGED
|
@@ -12,6 +12,8 @@ export {
|
|
|
12
12
|
views,
|
|
13
13
|
type TemporalGranularity,
|
|
14
14
|
type MutationsFilter,
|
|
15
|
+
mutationType,
|
|
16
|
+
type MutationType,
|
|
15
17
|
} from './types';
|
|
16
18
|
|
|
17
19
|
export type { MutationComparisonView, MutationComparisonProps } from './preact/mutationComparison/mutation-comparison';
|
|
@@ -47,3 +49,5 @@ export {
|
|
|
47
49
|
NumberRangeFilterChangedEvent,
|
|
48
50
|
NumberRangeValueChangedEvent,
|
|
49
51
|
} from './preact/numberRangeFilter/NumberRangeFilterChangedEvent';
|
|
52
|
+
|
|
53
|
+
export { type MeanProportionInterval } from './preact/mutationsOverTime/mutations-over-time';
|