@molgenis/vip-report-template 6.2.0 → 7.0.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/.nvmrc +1 -1
- package/.travis.yml +8 -8
- package/README.md +411 -1
- package/eslint.config.mjs +11 -0
- package/package.json +40 -35
- package/scripts/deploy_npm_registry.sh +5 -0
- package/src/App.tsx +30 -24
- package/src/assets/sass/main.scss +12 -4
- package/src/components/Allele.tsx +95 -0
- package/src/components/Anchor.tsx +1 -1
- package/src/components/Breadcrumb.tsx +6 -4
- package/src/components/DatasetDropdown.tsx +12 -25
- package/src/components/ErrorNotification.tsx +9 -0
- package/src/components/GenomeBrowser.tsx +40 -23
- package/src/components/HpoTerm.tsx +1 -1
- package/src/components/{record/Pager.tsx → Pager.tsx} +21 -14
- package/src/components/RecordsPerPage.tsx +9 -7
- package/src/components/RecordsTable.tsx +130 -0
- package/src/components/SampleTable.tsx +70 -98
- package/src/components/SearchBox.tsx +8 -2
- package/src/components/Sort.tsx +28 -25
- package/src/components/Table.tsx +16 -0
- package/src/components/Tooltip.tsx +20 -0
- package/src/components/VariantBreadcrumb.tsx +54 -0
- package/src/components/VariantConsequenceContainer.tsx +100 -0
- package/src/components/VariantConsequenceTable.tsx +58 -0
- package/src/components/VariantContainer.tsx +71 -0
- package/src/components/VariantFilters.tsx +27 -0
- package/src/components/VariantGenotypeTable.tsx +44 -0
- package/src/components/VariantInfoTable.tsx +24 -33
- package/src/components/VariantResults.tsx +103 -0
- package/src/components/VariantTable.tsx +62 -66
- package/src/components/VariantTypeSelect.tsx +34 -0
- package/src/components/VariantsContainer.tsx +150 -0
- package/src/components/VariantsContainerHeader.tsx +70 -0
- package/src/components/field/Field.tsx +80 -0
- package/src/components/field/FieldAlt.tsx +19 -0
- package/src/components/field/FieldChrom.tsx +6 -0
- package/src/components/{record/Id.tsx → field/FieldFilter.tsx} +2 -1
- package/src/components/field/FieldFormat.tsx +10 -0
- package/src/components/{record/Filter.tsx → field/FieldId.tsx} +1 -1
- package/src/components/field/FieldPos.tsx +6 -0
- package/src/components/field/FieldQual.tsx +6 -0
- package/src/components/field/FieldRef.tsx +8 -0
- package/src/components/field/composed/FieldClinVar.tsx +72 -0
- package/src/components/field/composed/FieldComposed.tsx +68 -0
- package/src/components/field/composed/FieldGene.tsx +39 -0
- package/src/components/field/composed/FieldGenotype.tsx +35 -0
- package/src/components/{record/format/GenotypeField.tsx → field/composed/FieldGenotypeSnvSv.tsx} +20 -16
- package/src/components/field/composed/FieldGenotypeStr.tsx +31 -0
- package/src/components/field/composed/FieldGnomAd.tsx +58 -0
- package/src/components/field/composed/FieldHpo.tsx +50 -0
- package/src/components/field/composed/FieldInheritanceModes.tsx +32 -0
- package/src/components/field/composed/FieldLocus.tsx +18 -0
- package/src/components/field/composed/FieldVipC.tsx +25 -0
- package/src/components/field/composed/FieldVipCS.tsx +15 -0
- package/src/components/field/composed/FieldVkgl.tsx +37 -0
- package/src/components/field/genotype/FieldGenotype.tsx +19 -0
- package/src/components/field/genotype/FieldGenotypeType.tsx +9 -0
- package/src/components/field/info/FieldConsequence.tsx +15 -0
- package/src/components/{record/info/Hgvs.tsx → field/info/FieldHgvs.tsx} +4 -6
- package/src/components/field/info/FieldInfo.tsx +27 -0
- package/src/components/{record/info/PubMed.tsx → field/info/FieldPubMed.tsx} +4 -7
- package/src/components/field/typed/FieldCategorical.tsx +17 -0
- package/src/components/{record/field/FieldValueCharacter.tsx → field/typed/FieldCharacter.tsx} +3 -2
- package/src/components/{record/field/FieldValueFlag.tsx → field/typed/FieldFlag.tsx} +3 -2
- package/src/components/{record/field/FieldValueFloat.tsx → field/typed/FieldFloat.tsx} +3 -2
- package/src/components/{record/field/FieldValueInteger.tsx → field/typed/FieldInteger.tsx} +3 -2
- package/src/components/{record/field/FieldValueString.tsx → field/typed/FieldString.tsx} +3 -2
- package/src/components/field/typed/FieldTyped.tsx +20 -0
- package/src/components/field/typed/FieldTypedItem.tsx +49 -0
- package/src/components/field/typed/FieldTypedMultiple.tsx +21 -0
- package/src/components/filter/Filter.tsx +56 -48
- package/src/components/filter/FilterWrapper.scss +23 -0
- package/src/components/filter/FilterWrapper.tsx +63 -0
- package/src/components/filter/composed/FilterAllelicImbalance.tsx +26 -0
- package/src/components/filter/composed/FilterComposed.tsx +92 -0
- package/src/components/filter/composed/FilterDeNovo.tsx +35 -0
- package/src/components/filter/composed/FilterHpo.tsx +16 -0
- package/src/components/filter/composed/FilterInheritance.tsx +42 -0
- package/src/components/filter/composed/FilterLocus.tsx +75 -0
- package/src/components/filter/composed/FilterVipC.tsx +16 -0
- package/src/components/filter/composed/FilterVipCS.tsx +16 -0
- package/src/components/filter/fixed/FilterAlt.tsx +20 -0
- package/src/components/filter/fixed/FilterChrom.tsx +22 -0
- package/src/components/filter/fixed/FilterFilter.tsx +20 -0
- package/src/components/filter/fixed/FilterFixed.tsx +96 -0
- package/src/components/filter/fixed/FilterId.tsx +20 -0
- package/src/components/filter/fixed/FilterPos.tsx +22 -0
- package/src/components/filter/fixed/FilterQual.tsx +21 -0
- package/src/components/filter/fixed/FilterRef.tsx +22 -0
- package/src/components/filter/typed/FilterCategorical.tsx +119 -0
- package/src/components/filter/typed/FilterFlag.tsx +23 -0
- package/src/components/filter/typed/FilterInterval.tsx +72 -0
- package/src/components/filter/typed/FilterString.tsx +43 -0
- package/src/components/filter/typed/FilterTyped.tsx +56 -0
- package/src/components/form/ButtonApply.tsx +11 -0
- package/src/components/form/ButtonDownload.tsx +11 -0
- package/src/components/form/ButtonReset.tsx +9 -0
- package/src/components/{Checkbox.tsx → form/Checkbox.tsx} +4 -9
- package/src/components/form/Input.tsx +19 -0
- package/src/components/form/Select.scss +7 -0
- package/src/components/form/Select.tsx +34 -0
- package/src/components/tree/DecisionTreeBoolMultiQuery.tsx +1 -1
- package/src/components/tree/DecisionTreeBoolQuery.tsx +1 -1
- package/src/components/tree/DecisionTreeNode.tsx +41 -39
- package/src/components/tree/DecisionTreeNodeBool.tsx +1 -1
- package/src/components/tree/DecisionTreeNodeBoolMulti.tsx +1 -1
- package/src/components/tree/DecisionTreeNodeCategorical.tsx +1 -1
- package/src/components/tree/DecisionTreeNodeExists.tsx +1 -1
- package/src/components/tree/DecisionTreeNodeLeaf.tsx +1 -1
- package/src/components/tree/DecisionTreeOutcomeNode.tsx +1 -1
- package/src/components/tree/DecisionTreePath.tsx +1 -1
- package/src/igv.d.ts +2 -1
- package/src/index.tsx +48 -19
- package/src/mocks/GRCh37/decisionTree.json +23 -22
- package/src/mocks/GRCh37/field_metadata.json +435 -95
- package/src/mocks/GRCh37/sampleTree.json +21 -1
- package/src/mocks/GRCh37/static.ts +62 -134
- package/src/mocks/GRCh37/vcf/family.vcf.blob +9 -3
- package/src/mocks/GRCh38/decisionTree.json +52 -33
- package/src/mocks/GRCh38/decisionTreeStr.json +572 -0
- package/src/mocks/GRCh38/fasta/chr1_149380406-149403321.fasta.gz.blob +0 -0
- package/src/mocks/GRCh38/field_metadata.json +435 -95
- package/src/mocks/GRCh38/sampleTree.json +175 -0
- package/src/mocks/GRCh38/static.ts +101 -42
- package/src/mocks/GRCh38/str.cram.blob +0 -0
- package/src/mocks/GRCh38/str.cram.crai.blob +0 -0
- package/src/mocks/GRCh38/vcf/family.vcf.blob +25 -24
- package/src/mocks/GRCh38/vcf/no_vep.vcf.blob +29 -28
- package/src/mocks/GRCh38/vcf/samples_0.vcf.blob +28 -27
- package/src/mocks/GRCh38/vcf/samples_1.vcf.blob +29 -28
- package/src/mocks/GRCh38/vcf/samples_100.vcf.blob +28 -27
- package/src/mocks/GRCh38/vcf/str.vcf.blob +321 -0
- package/src/mocks/MockApiClient.ts +339 -332
- package/src/mocks/config_cram.json +701 -0
- package/src/mocks/config_vcf.json +699 -0
- package/src/store/app.ts +30 -0
- package/src/store/index.tsx +3 -168
- package/src/store/variants.ts +182 -0
- package/src/types/config.d.ts +190 -0
- package/src/types/configCellComposed.d.ts +86 -0
- package/src/types/configCells.d.ts +129 -0
- package/src/types/configFilter.d.ts +80 -0
- package/src/types/configFilterComposed.d.ts +60 -0
- package/src/types/configSort.d.ts +13 -0
- package/src/types/filter.d.ts +17 -0
- package/src/types/store.d.ts +34 -0
- package/src/utils/api.ts +281 -0
- package/src/utils/config/config.ts +182 -0
- package/src/utils/config/configCells.ts +74 -0
- package/src/utils/config/configCellsComposed.ts +508 -0
- package/src/utils/config/configCellsField.ts +61 -0
- package/src/utils/config/configCellsFixed.ts +126 -0
- package/src/utils/config/configFilters.ts +46 -0
- package/src/utils/config/configFiltersComposed.ts +208 -0
- package/src/utils/config/configFiltersField.ts +49 -0
- package/src/utils/config/configFiltersFixed.ts +106 -0
- package/src/utils/config/configSorts.ts +44 -0
- package/src/utils/config/configValidator.ts +380 -0
- package/src/utils/config/configVip.ts +25 -0
- package/src/utils/csq.ts +115 -0
- package/src/utils/decisionTree.ts +45 -0
- package/src/utils/download.ts +30 -0
- package/src/utils/error.ts +69 -0
- package/src/utils/query/query.ts +55 -0
- package/src/utils/query/queryFilter.ts +132 -0
- package/src/utils/query/queryFilterComposed.ts +247 -0
- package/src/utils/query/queryFilterField.ts +75 -0
- package/src/utils/query/queryFilterFixed.ts +44 -0
- package/src/utils/query/querySample.ts +18 -0
- package/src/utils/query/queryVariantType.ts +76 -0
- package/src/utils/query/selector.ts +41 -0
- package/src/utils/{sortUtils.ts → query/sort.ts} +32 -11
- package/src/utils/sample.ts +19 -35
- package/src/utils/utils.ts +66 -2
- package/src/utils/variantType.ts +43 -0
- package/src/utils/vcf.ts +352 -0
- package/src/views/Help.tsx +109 -114
- package/src/views/Home.tsx +3 -2
- package/src/views/Sample.tsx +12 -7
- package/src/views/SampleVariant.tsx +23 -112
- package/src/views/SampleVariantConsequence.tsx +54 -144
- package/src/views/SampleVariants.tsx +33 -445
- package/src/views/SampleVariantsRedirect.tsx +20 -0
- package/src/views/Samples.tsx +7 -10
- package/src/views/Variant.tsx +31 -61
- package/src/views/VariantConsequence.tsx +42 -72
- package/src/views/Variants.tsx +29 -138
- package/src/views/VariantsRedirect.tsx +25 -0
- package/src/views/data/data.tsx +32 -6
- package/tests/store/variants.test.ts +122 -0
- package/tests/utils/config/config.test.ts +167 -0
- package/tests/utils/config/configCells.test.ts +86 -0
- package/tests/utils/config/configCellsComposed.test.ts +1163 -0
- package/tests/utils/config/configCellsField.test.ts +164 -0
- package/tests/utils/config/configCellsFixed.test.ts +99 -0
- package/tests/utils/config/configFilters.test.ts +80 -0
- package/tests/utils/config/configFiltersComposed.test.ts +504 -0
- package/tests/utils/config/configFiltersField.test.ts +140 -0
- package/tests/utils/config/configFiltersFixed.test.ts +81 -0
- package/tests/utils/config/configSorts.test.ts +55 -0
- package/tests/utils/config/configValidator.test.ts +56 -0
- package/tests/utils/config/configVip.test.ts +53 -0
- package/tests/utils/decisionTree.test.ts +71 -0
- package/tests/utils/download.test.ts +20 -0
- package/tests/utils/query/query.test.ts +84 -0
- package/tests/utils/query/queryFilter.test.ts +243 -0
- package/tests/utils/query/queryFilterComposed.test.ts +301 -0
- package/tests/utils/query/queryFilterField.test.ts +75 -0
- package/tests/utils/query/queryFilterFixed.test.ts +86 -0
- package/tests/utils/query/querySample.test.ts +45 -0
- package/tests/utils/query/queryVariantType.test.ts +56 -0
- package/{src/__tests__/sortUtils.test.ts → tests/utils/query/sort.test.ts} +3 -4
- package/tests/utils/sample.test.ts +259 -0
- package/tests/utils/utils.test.ts +120 -0
- package/tests/utils/variantType.test.ts +48 -0
- package/tests/utils/vcf.test.ts +649 -0
- package/tsconfig.json +6 -2
- package/vite.config.mts +20 -3
- package/.eslintignore +0 -4
- package/.eslintrc.js +0 -23
- package/src/Api.ts +0 -12
- package/src/__tests__/decisionTreeUtils.test.ts +0 -75
- package/src/__tests__/field.test.ts +0 -107
- package/src/__tests__/query.test.ts +0 -188
- package/src/__tests__/sample.test.ts +0 -184
- package/src/__tests__/utils.test.ts +0 -24
- package/src/__tests__/viewUtils.test.ts +0 -125
- package/src/components/ConsequenceTable.tsx +0 -45
- package/src/components/Error.tsx +0 -9
- package/src/components/FieldHeader.tsx +0 -26
- package/src/components/InfoCollapsablePane.tsx +0 -90
- package/src/components/VariantInfoNestedTable.tsx +0 -127
- package/src/components/VariantSampleTable.tsx +0 -58
- package/src/components/VariantsSampleTable.tsx +0 -184
- package/src/components/VariantsTable.tsx +0 -125
- package/src/components/filter/FilterAllelicBalance.tsx +0 -81
- package/src/components/filter/FilterCategorical.tsx +0 -81
- package/src/components/filter/FilterClinVar.tsx +0 -21
- package/src/components/filter/FilterGene.tsx +0 -34
- package/src/components/filter/FilterHpo.tsx +0 -161
- package/src/components/filter/FilterInheritance.tsx +0 -162
- package/src/components/filter/FilterIntegerGq.tsx +0 -47
- package/src/components/filter/FilterVI.tsx +0 -68
- package/src/components/filter/FilterVariantType.tsx +0 -146
- package/src/components/filter/Filters.tsx +0 -29
- package/src/components/filter/InfoFilter.tsx +0 -39
- package/src/components/filter/InfoFilters.tsx +0 -35
- package/src/components/filter/SampleFilters.tsx +0 -93
- package/src/components/filter/SamplesFilters.tsx +0 -33
- package/src/components/record/Allele.tsx +0 -38
- package/src/components/record/AlleleBreakend.tsx +0 -5
- package/src/components/record/AlleleMissing.tsx +0 -5
- package/src/components/record/AlleleNucs.tsx +0 -49
- package/src/components/record/AlleleSymbolic.tsx +0 -5
- package/src/components/record/Alt.tsx +0 -17
- package/src/components/record/Chrom.tsx +0 -5
- package/src/components/record/Format.tsx +0 -40
- package/src/components/record/Info.tsx +0 -55
- package/src/components/record/Pos.tsx +0 -5
- package/src/components/record/Qual.tsx +0 -5
- package/src/components/record/RecordDownload.tsx +0 -66
- package/src/components/record/Ref.tsx +0 -6
- package/src/components/record/field/Field.tsx +0 -36
- package/src/components/record/field/FieldMultipleValue.tsx +0 -22
- package/src/components/record/field/FieldSingleValue.tsx +0 -35
- package/src/components/record/info/ClinVar.tsx +0 -81
- package/src/components/record/info/Consequence.tsx +0 -18
- package/src/components/record/info/Gene.tsx +0 -56
- package/src/components/record/info/GnomAD.tsx +0 -54
- package/src/components/record/info/Hpo.tsx +0 -52
- package/src/components/record/info/InheritanceModes.tsx +0 -22
- package/src/components/record/info/VipC.tsx +0 -23
- package/src/components/record/info/Vkgl.tsx +0 -42
- package/src/mocks/GRCh37/vcf/no_vep.vcf.blob +0 -61
- package/src/mocks/GRCh37/vcf/samples_0.vcf.blob +0 -93
- package/src/mocks/GRCh37/vcf/samples_1.vcf.blob +0 -93
- package/src/mocks/GRCh37/vcf/samples_100.vcf.blob +0 -93
- package/src/utils/ApiUtils.ts +0 -263
- package/src/utils/csqUtils.ts +0 -27
- package/src/utils/decisionTreeUtils.ts +0 -31
- package/src/utils/field.ts +0 -49
- package/src/utils/query.ts +0 -154
- package/src/utils/viewUtils.ts +0 -32
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { ComposedQueryOperator, Query } from "@molgenis/vip-report-api";
|
|
2
|
+
import { FilterValueMap } from "../../types/configFilter";
|
|
3
|
+
import { VariantType } from "../variantType.ts";
|
|
4
|
+
|
|
5
|
+
import { Config } from "../../types/config";
|
|
6
|
+
import { SampleContainer } from "../api.ts";
|
|
7
|
+
import { createQueryFilters } from "./queryFilter.ts";
|
|
8
|
+
import { createQueryVariantType } from "./queryVariantType.ts";
|
|
9
|
+
import { createQuerySample } from "./querySample.ts";
|
|
10
|
+
|
|
11
|
+
export function createQuery(
|
|
12
|
+
config: Config,
|
|
13
|
+
variantType: VariantType,
|
|
14
|
+
sample: SampleContainer | null,
|
|
15
|
+
filterValues: FilterValueMap,
|
|
16
|
+
): Query | null {
|
|
17
|
+
const queryParts: Query[] = [];
|
|
18
|
+
|
|
19
|
+
const queryVariantType = createQueryVariantType(variantType);
|
|
20
|
+
if (queryVariantType !== null) {
|
|
21
|
+
queryParts.push(queryVariantType);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
if (sample !== null) {
|
|
25
|
+
const querySample = createQuerySample(config.vip, sample);
|
|
26
|
+
queryParts.push(querySample);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const queryFilters = createQueryFilters(config.variants.filters, filterValues);
|
|
30
|
+
if (queryFilters !== null) {
|
|
31
|
+
queryParts.push(queryFilters);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
return queryParts.length > 0 ? createQueryComposed(queryParts, "and") : null;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export function createQueryComposed(queryParts: Query[], operator: ComposedQueryOperator): Query {
|
|
38
|
+
const query: Query | null = createQueryComposedNullable(queryParts, operator);
|
|
39
|
+
if (query === null) {
|
|
40
|
+
throw new Error("query cannot be null");
|
|
41
|
+
}
|
|
42
|
+
return query;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export function createQueryComposedNullable(queryParts: Query[], operator: ComposedQueryOperator): Query | null {
|
|
46
|
+
let query: Query | null;
|
|
47
|
+
if (queryParts.length === 0) {
|
|
48
|
+
query = null;
|
|
49
|
+
} else if (queryParts.length === 1) {
|
|
50
|
+
query = queryParts[0]!;
|
|
51
|
+
} else {
|
|
52
|
+
query = { operator, args: queryParts }; // TODO simplify query is all query parts are composed queries with the same operator as the given operator
|
|
53
|
+
}
|
|
54
|
+
return query;
|
|
55
|
+
}
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
import {
|
|
2
|
+
ConfigFilter,
|
|
3
|
+
ConfigFilterField,
|
|
4
|
+
FilterValue,
|
|
5
|
+
FilterValueFixed,
|
|
6
|
+
FilterValueInterval,
|
|
7
|
+
FilterValueMap,
|
|
8
|
+
FilterValueString,
|
|
9
|
+
} from "../../types/configFilter";
|
|
10
|
+
import { Query, Selector } from "@molgenis/vip-report-api";
|
|
11
|
+
import { createQueryFilterComposed } from "./queryFilterComposed.ts";
|
|
12
|
+
import { ConfigFilterComposed } from "../../types/configFilterComposed";
|
|
13
|
+
import { createQueryFilterFixed } from "./queryFilterFixed.ts";
|
|
14
|
+
import { RuntimeError, UnexpectedEnumValueException } from "../error.ts";
|
|
15
|
+
import { ConfigFilters } from "../../types/config";
|
|
16
|
+
import { createQueryComposed, createQueryComposedNullable } from "./query.ts";
|
|
17
|
+
import { createQueryFilterField } from "./queryFilterField.ts";
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Create API query for state of list of filters
|
|
21
|
+
*
|
|
22
|
+
* @param filterConfigs filter configurations
|
|
23
|
+
* @param filterValues filter values
|
|
24
|
+
*/
|
|
25
|
+
export function createQueryFilters(filterConfigs: ConfigFilters, filterValues: FilterValueMap): Query | null {
|
|
26
|
+
// TODO discuss: can we have id collisions between different types?
|
|
27
|
+
const queryParts = filterConfigs
|
|
28
|
+
.map((filter) => createQueryFilter(filter, filterValues[filter.id]!))
|
|
29
|
+
.filter((query) => query !== null);
|
|
30
|
+
return createQueryComposedNullable(queryParts, "and");
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Create API query for state of one filter
|
|
35
|
+
*
|
|
36
|
+
* @param filterConfig filter configuration
|
|
37
|
+
* @param filterValue filter value
|
|
38
|
+
*/
|
|
39
|
+
function createQueryFilter(filterConfig: ConfigFilter, filterValue: FilterValue): Query | null {
|
|
40
|
+
let query: Query | null;
|
|
41
|
+
if (filterValue !== undefined) {
|
|
42
|
+
switch (filterConfig.type) {
|
|
43
|
+
case "composed":
|
|
44
|
+
query = createQueryFilterComposed(filterConfig as ConfigFilterComposed, filterValue);
|
|
45
|
+
break;
|
|
46
|
+
case "fixed":
|
|
47
|
+
query = createQueryFilterFixed(filterConfig, filterValue as FilterValueFixed);
|
|
48
|
+
break;
|
|
49
|
+
case "genotype":
|
|
50
|
+
case "info":
|
|
51
|
+
query = createQueryFilterField(filterConfig as ConfigFilterField, filterValue);
|
|
52
|
+
break;
|
|
53
|
+
default:
|
|
54
|
+
throw new UnexpectedEnumValueException(filterConfig.type);
|
|
55
|
+
}
|
|
56
|
+
} else {
|
|
57
|
+
query = null;
|
|
58
|
+
}
|
|
59
|
+
return query;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
export function createQueryFilterString(
|
|
63
|
+
selector: Selector,
|
|
64
|
+
filterValue: FilterValueString,
|
|
65
|
+
multiValue: boolean,
|
|
66
|
+
nestedValue: boolean,
|
|
67
|
+
): Query {
|
|
68
|
+
// null values
|
|
69
|
+
// multi=false --> value=null
|
|
70
|
+
// multi=true --> value=[] or value=[..., null, ...]
|
|
71
|
+
const filterValues = filterValue.map((value) => (value !== "__null" ? value : null));
|
|
72
|
+
|
|
73
|
+
const queryParts: Query[] = [];
|
|
74
|
+
if (filterValues.length > 0) {
|
|
75
|
+
queryParts.push({
|
|
76
|
+
selector,
|
|
77
|
+
operator: nestedValue ? (multiValue ? "any_has_any" : "has_any") : multiValue ? "has_any" : "in",
|
|
78
|
+
args: filterValues,
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
if (multiValue && filterValues.findIndex((value) => value === null) !== -1) {
|
|
83
|
+
queryParts.push({
|
|
84
|
+
selector,
|
|
85
|
+
operator: nestedValue ? (multiValue ? "any_has_any" : "has_any") : "==",
|
|
86
|
+
args: multiValue ? [] : null,
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
return createQueryComposed(queryParts, "or");
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
export function createQueryFilterClosedInterval(selector: Selector, filterValue: FilterValueInterval): Query {
|
|
93
|
+
if (filterValue.left === undefined && filterValue.right === undefined) throw new RuntimeError();
|
|
94
|
+
|
|
95
|
+
const queryParts: Query[] = [];
|
|
96
|
+
if (filterValue.left !== undefined) {
|
|
97
|
+
queryParts.push({
|
|
98
|
+
selector,
|
|
99
|
+
operator: ">=",
|
|
100
|
+
args: filterValue.left,
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
if (filterValue.right !== undefined) {
|
|
104
|
+
queryParts.push({
|
|
105
|
+
selector,
|
|
106
|
+
operator: "<=",
|
|
107
|
+
args: filterValue.right,
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
return createQueryComposed(queryParts, "and");
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
export function createQueryFilterClosedIntervalOutside(selector: Selector, filterValue: FilterValueInterval): Query {
|
|
114
|
+
if (filterValue.left === undefined && filterValue.right === undefined) throw new RuntimeError();
|
|
115
|
+
|
|
116
|
+
const queryParts: Query[] = [];
|
|
117
|
+
if (filterValue.left !== undefined) {
|
|
118
|
+
queryParts.push({
|
|
119
|
+
selector,
|
|
120
|
+
operator: "<",
|
|
121
|
+
args: filterValue.left,
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
if (filterValue.right !== undefined) {
|
|
125
|
+
queryParts.push({
|
|
126
|
+
selector,
|
|
127
|
+
operator: ">",
|
|
128
|
+
args: filterValue.right,
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
return createQueryComposed(queryParts, "or");
|
|
132
|
+
}
|
|
@@ -0,0 +1,247 @@
|
|
|
1
|
+
import {
|
|
2
|
+
ConfigFilterAllelicImbalance,
|
|
3
|
+
ConfigFilterComposed,
|
|
4
|
+
ConfigFilterDeNovo,
|
|
5
|
+
ConfigFilterHpo,
|
|
6
|
+
ConfigFilterInheritanceMatch,
|
|
7
|
+
ConfigFilterVipC,
|
|
8
|
+
ConfigFilterVipCS,
|
|
9
|
+
FilterValueAllelicImbalance,
|
|
10
|
+
FilterValueDeNovo,
|
|
11
|
+
FilterValueHpo,
|
|
12
|
+
FilterValueInheritanceMatch,
|
|
13
|
+
FilterValueLocus,
|
|
14
|
+
FilterValueVipC,
|
|
15
|
+
FilterValueVipCS,
|
|
16
|
+
} from "../../types/configFilterComposed";
|
|
17
|
+
import { FilterValue } from "../../types/configFilter";
|
|
18
|
+
import { Query } from "@molgenis/vip-report-api";
|
|
19
|
+
import { createQueryComposed } from "./query.ts";
|
|
20
|
+
import { createSelectorInfo, createSelectorSample } from "./selector.ts";
|
|
21
|
+
import {
|
|
22
|
+
createQueryFilterClosedInterval,
|
|
23
|
+
createQueryFilterClosedIntervalOutside,
|
|
24
|
+
createQueryFilterString,
|
|
25
|
+
} from "./queryFilter.ts";
|
|
26
|
+
import { createQueryFilterFieldCategorical } from "./queryFilterField.ts";
|
|
27
|
+
|
|
28
|
+
export function createQueryFilterComposed(filter: ConfigFilterComposed, filterValue: FilterValue): Query {
|
|
29
|
+
let query: Query;
|
|
30
|
+
switch (filter.id) {
|
|
31
|
+
case "composed/hpo":
|
|
32
|
+
query = createQueryFilterHpo(filter as ConfigFilterHpo, filterValue as FilterValueHpo);
|
|
33
|
+
break;
|
|
34
|
+
case "composed/locus":
|
|
35
|
+
query = createQueryFilterLocus(filterValue as FilterValueLocus);
|
|
36
|
+
break;
|
|
37
|
+
case "composed/allelicImbalance":
|
|
38
|
+
query = createQueryFilterAllelicImbalance(
|
|
39
|
+
filter as ConfigFilterAllelicImbalance,
|
|
40
|
+
filterValue as FilterValueAllelicImbalance,
|
|
41
|
+
);
|
|
42
|
+
break;
|
|
43
|
+
case "composed/inheritanceMatch":
|
|
44
|
+
query = createQueryFilterInheritanceMatch(
|
|
45
|
+
filter as ConfigFilterInheritanceMatch,
|
|
46
|
+
filterValue as FilterValueInheritanceMatch,
|
|
47
|
+
);
|
|
48
|
+
break;
|
|
49
|
+
case "composed/deNovo":
|
|
50
|
+
query = createQueryFilterDeNovo(filter as ConfigFilterDeNovo, filterValue as FilterValueDeNovo);
|
|
51
|
+
break;
|
|
52
|
+
case "composed/vipC":
|
|
53
|
+
query = createQueryFilterVipC(filter as ConfigFilterVipC, filterValue as FilterValueVipC);
|
|
54
|
+
break;
|
|
55
|
+
case "composed/vipCS":
|
|
56
|
+
query = createQueryFilterVipCS(filter as ConfigFilterVipCS, filterValue as FilterValueVipCS);
|
|
57
|
+
break;
|
|
58
|
+
default:
|
|
59
|
+
throw new Error(`unexpected filter id '${filter.id}'`);
|
|
60
|
+
}
|
|
61
|
+
return query;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function createQueryFilterHpo(filter: ConfigFilterHpo, filterValue: FilterValueHpo): Query {
|
|
65
|
+
const field = filter.field;
|
|
66
|
+
const selector = createSelectorInfo(field);
|
|
67
|
+
return createQueryFilterFieldCategorical(selector, field, filterValue);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
function createQueryFilterLocus(filterValue: FilterValueLocus): Query {
|
|
71
|
+
const queryParts: Query[] = [createQueryFilterString(["c"], [filterValue.chromosome], false, false)];
|
|
72
|
+
|
|
73
|
+
if (filterValue.start !== undefined || filterValue.end !== undefined) {
|
|
74
|
+
const posQuery = createQueryFilterClosedInterval(["p"], { left: filterValue.start, right: filterValue.end });
|
|
75
|
+
queryParts.push(posQuery);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
return createQueryComposed(queryParts, "and");
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
function createQueryFilterAllelicImbalance(
|
|
82
|
+
filter: ConfigFilterAllelicImbalance,
|
|
83
|
+
filterValue: FilterValueAllelicImbalance,
|
|
84
|
+
): Query {
|
|
85
|
+
const viabSelector = createSelectorSample(filter.sample, filter.viabField);
|
|
86
|
+
const gtSelector = [...createSelectorSample(filter.sample, filter.genotypeField), "t"];
|
|
87
|
+
|
|
88
|
+
const queryParts: Query[] = [];
|
|
89
|
+
if (filterValue.includes("true")) {
|
|
90
|
+
const queryPartsTrue: Query[] = [];
|
|
91
|
+
queryPartsTrue.push(
|
|
92
|
+
createQueryComposed(
|
|
93
|
+
[
|
|
94
|
+
{
|
|
95
|
+
operator: "in",
|
|
96
|
+
selector: gtSelector,
|
|
97
|
+
args: ["hom_a", "hom_r"],
|
|
98
|
+
},
|
|
99
|
+
createQueryFilterClosedInterval(viabSelector, { left: 0.02, right: 0.98 }),
|
|
100
|
+
],
|
|
101
|
+
"and",
|
|
102
|
+
),
|
|
103
|
+
);
|
|
104
|
+
queryPartsTrue.push(
|
|
105
|
+
createQueryComposed(
|
|
106
|
+
[
|
|
107
|
+
{
|
|
108
|
+
operator: "==",
|
|
109
|
+
selector: gtSelector,
|
|
110
|
+
args: "het",
|
|
111
|
+
},
|
|
112
|
+
createQueryFilterClosedIntervalOutside(viabSelector, { left: 0.2, right: 0.8 }),
|
|
113
|
+
],
|
|
114
|
+
"and",
|
|
115
|
+
),
|
|
116
|
+
);
|
|
117
|
+
queryParts.push(createQueryComposed(queryPartsTrue, "or"));
|
|
118
|
+
}
|
|
119
|
+
if (filterValue.includes("false")) {
|
|
120
|
+
const queryPartsFalse: Query[] = [];
|
|
121
|
+
queryPartsFalse.push(
|
|
122
|
+
createQueryComposed(
|
|
123
|
+
[
|
|
124
|
+
{
|
|
125
|
+
operator: "in",
|
|
126
|
+
selector: gtSelector,
|
|
127
|
+
args: ["hom_a", "hom_r"],
|
|
128
|
+
},
|
|
129
|
+
createQueryFilterClosedIntervalOutside(viabSelector, { left: 0.02, right: 0.98 }),
|
|
130
|
+
],
|
|
131
|
+
"and",
|
|
132
|
+
),
|
|
133
|
+
);
|
|
134
|
+
queryPartsFalse.push(
|
|
135
|
+
createQueryComposed(
|
|
136
|
+
[
|
|
137
|
+
{
|
|
138
|
+
operator: "==",
|
|
139
|
+
selector: gtSelector,
|
|
140
|
+
args: "het",
|
|
141
|
+
},
|
|
142
|
+
createQueryFilterClosedInterval(viabSelector, { left: 0.2, right: 0.8 }),
|
|
143
|
+
],
|
|
144
|
+
"and",
|
|
145
|
+
),
|
|
146
|
+
);
|
|
147
|
+
queryParts.push(createQueryComposed(queryPartsFalse, "or"));
|
|
148
|
+
}
|
|
149
|
+
if (filterValue.includes("__null")) {
|
|
150
|
+
const queryPartsUndefined: Query[] = [];
|
|
151
|
+
queryPartsUndefined.push({
|
|
152
|
+
selector: viabSelector,
|
|
153
|
+
operator: "==",
|
|
154
|
+
args: null,
|
|
155
|
+
});
|
|
156
|
+
queryPartsUndefined.push({
|
|
157
|
+
selector: viabSelector,
|
|
158
|
+
operator: "==",
|
|
159
|
+
args: undefined,
|
|
160
|
+
});
|
|
161
|
+
queryParts.push(createQueryComposed(queryPartsUndefined, "or"));
|
|
162
|
+
}
|
|
163
|
+
return createQueryComposed(queryParts, "or");
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
function createQueryFilterInheritanceMatch(
|
|
167
|
+
filter: ConfigFilterInheritanceMatch,
|
|
168
|
+
filterValue: FilterValueInheritanceMatch,
|
|
169
|
+
): Query {
|
|
170
|
+
const vimSelector = createSelectorSample(filter.sample, filter.vimField);
|
|
171
|
+
const queryParts: Query[] = [];
|
|
172
|
+
if (filterValue.includes("true")) {
|
|
173
|
+
queryParts.push({
|
|
174
|
+
operator: "==",
|
|
175
|
+
selector: vimSelector,
|
|
176
|
+
args: 1,
|
|
177
|
+
});
|
|
178
|
+
}
|
|
179
|
+
if (filterValue.includes("false")) {
|
|
180
|
+
queryParts.push({
|
|
181
|
+
operator: "==",
|
|
182
|
+
selector: vimSelector,
|
|
183
|
+
args: 0,
|
|
184
|
+
});
|
|
185
|
+
}
|
|
186
|
+
if (filterValue.includes("potential")) {
|
|
187
|
+
const queryPartsUndefined: Query[] = [];
|
|
188
|
+
queryPartsUndefined.push({
|
|
189
|
+
selector: vimSelector,
|
|
190
|
+
operator: "==",
|
|
191
|
+
args: null,
|
|
192
|
+
});
|
|
193
|
+
queryPartsUndefined.push({
|
|
194
|
+
selector: vimSelector,
|
|
195
|
+
operator: "==",
|
|
196
|
+
args: undefined,
|
|
197
|
+
});
|
|
198
|
+
queryParts.push(createQueryComposed(queryPartsUndefined, "or"));
|
|
199
|
+
}
|
|
200
|
+
return createQueryComposed(queryParts, "and");
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
function createQueryFilterDeNovo(filter: ConfigFilterDeNovo, filterValue: FilterValueDeNovo): Query {
|
|
204
|
+
const vidSelector = createSelectorSample(filter.sample, filter.vidField);
|
|
205
|
+
const queryParts: Query[] = [];
|
|
206
|
+
if (filterValue.includes("true")) {
|
|
207
|
+
queryParts.push({
|
|
208
|
+
operator: "==",
|
|
209
|
+
selector: vidSelector,
|
|
210
|
+
args: 1,
|
|
211
|
+
});
|
|
212
|
+
}
|
|
213
|
+
if (filterValue.includes("false")) {
|
|
214
|
+
queryParts.push({
|
|
215
|
+
operator: "==",
|
|
216
|
+
selector: vidSelector,
|
|
217
|
+
args: 0,
|
|
218
|
+
});
|
|
219
|
+
}
|
|
220
|
+
if (filterValue.includes("potential")) {
|
|
221
|
+
const queryPartsUndefined: Query[] = [];
|
|
222
|
+
queryPartsUndefined.push({
|
|
223
|
+
selector: vidSelector,
|
|
224
|
+
operator: "==",
|
|
225
|
+
args: null,
|
|
226
|
+
});
|
|
227
|
+
queryPartsUndefined.push({
|
|
228
|
+
selector: vidSelector,
|
|
229
|
+
operator: "==",
|
|
230
|
+
args: undefined,
|
|
231
|
+
});
|
|
232
|
+
queryParts.push(createQueryComposed(queryPartsUndefined, "or"));
|
|
233
|
+
}
|
|
234
|
+
return createQueryComposed(queryParts, "and");
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
function createQueryFilterVipC(filter: ConfigFilterVipC, filterValue: FilterValueVipC): Query {
|
|
238
|
+
const field = filter.field;
|
|
239
|
+
const selector = createSelectorInfo(field);
|
|
240
|
+
return createQueryFilterFieldCategorical(selector, field, filterValue);
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
function createQueryFilterVipCS(filter: ConfigFilterVipCS, filterValue: FilterValueVipCS): Query {
|
|
244
|
+
const field = filter.field;
|
|
245
|
+
const selector = createSelectorSample(filter.sample, field);
|
|
246
|
+
return createQueryFilterFieldCategorical(selector, field, filterValue);
|
|
247
|
+
}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { Query, Selector, SelectorPart } from "@molgenis/vip-report-api";
|
|
2
|
+
import { FieldMetadata } from "@molgenis/vip-report-vcf";
|
|
3
|
+
import {
|
|
4
|
+
ConfigFilterField,
|
|
5
|
+
ConfigFilterFormat,
|
|
6
|
+
FilterValue,
|
|
7
|
+
FilterValueCategorical,
|
|
8
|
+
FilterValueInterval,
|
|
9
|
+
FilterValueString,
|
|
10
|
+
} from "../../types/configFilter";
|
|
11
|
+
import { UnexpectedEnumValueException } from "../error.ts";
|
|
12
|
+
import { createSelectorInfo, createSelectorSample } from "./selector.ts";
|
|
13
|
+
import { createQueryFilterClosedInterval, createQueryFilterString } from "./queryFilter.ts";
|
|
14
|
+
|
|
15
|
+
export function createQueryFilterField(filter: ConfigFilterField, filterValue: FilterValue): Query {
|
|
16
|
+
const selector = createSelectorFilter(filter);
|
|
17
|
+
const field = filter.field;
|
|
18
|
+
|
|
19
|
+
let query: Query;
|
|
20
|
+
switch (filter.field.type) {
|
|
21
|
+
case "CATEGORICAL":
|
|
22
|
+
query = createQueryFilterFieldCategorical(selector, field, filterValue as FilterValueCategorical);
|
|
23
|
+
break;
|
|
24
|
+
case "CHARACTER":
|
|
25
|
+
case "STRING":
|
|
26
|
+
query = createQueryFilterFieldString(selector, field, filterValue as FilterValueString);
|
|
27
|
+
break;
|
|
28
|
+
case "FLOAT":
|
|
29
|
+
case "INTEGER":
|
|
30
|
+
query = createQueryFilterClosedInterval(selector, filterValue as FilterValueInterval);
|
|
31
|
+
break;
|
|
32
|
+
case "FLAG":
|
|
33
|
+
query = createQueryFilterFlag();
|
|
34
|
+
break;
|
|
35
|
+
default:
|
|
36
|
+
throw new UnexpectedEnumValueException(field.type);
|
|
37
|
+
}
|
|
38
|
+
return query;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function createSelectorFilter(filter: ConfigFilterField) {
|
|
42
|
+
let selector: SelectorPart[];
|
|
43
|
+
switch (filter.type) {
|
|
44
|
+
case "genotype":
|
|
45
|
+
selector = createSelectorSample((filter as ConfigFilterFormat).sample, filter.field);
|
|
46
|
+
break;
|
|
47
|
+
case "info":
|
|
48
|
+
selector = createSelectorInfo(filter.field);
|
|
49
|
+
break;
|
|
50
|
+
case "composed":
|
|
51
|
+
default:
|
|
52
|
+
throw new UnexpectedEnumValueException(filter.type);
|
|
53
|
+
}
|
|
54
|
+
return selector;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export function createQueryFilterFieldCategorical(
|
|
58
|
+
selector: Selector,
|
|
59
|
+
field: FieldMetadata,
|
|
60
|
+
filterValue: FilterValueCategorical,
|
|
61
|
+
): Query {
|
|
62
|
+
const multiValue = field.number.count !== 1;
|
|
63
|
+
const nestedValue = field.parent !== undefined;
|
|
64
|
+
return createQueryFilterString(selector, filterValue, multiValue, nestedValue);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
function createQueryFilterFlag(): Query {
|
|
68
|
+
throw new Error("not implemented"); // FIXME support flag filter queries
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
function createQueryFilterFieldString(selector: Selector, field: FieldMetadata, filterValue: FilterValueString): Query {
|
|
72
|
+
const multiValue = field.number.count !== 1;
|
|
73
|
+
const nestedValue = field.parent !== undefined;
|
|
74
|
+
return createQueryFilterString(selector, filterValue, multiValue, nestedValue);
|
|
75
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import {
|
|
2
|
+
ConfigFilterFixed,
|
|
3
|
+
FilterValueAlt,
|
|
4
|
+
FilterValueChrom,
|
|
5
|
+
FilterValueFilter,
|
|
6
|
+
FilterValueFixed,
|
|
7
|
+
FilterValueId,
|
|
8
|
+
FilterValuePos,
|
|
9
|
+
FilterValueQual,
|
|
10
|
+
FilterValueRef,
|
|
11
|
+
} from "../../types/configFilter";
|
|
12
|
+
import { Query } from "@molgenis/vip-report-api";
|
|
13
|
+
import { UnexpectedEnumValueException } from "../error.ts";
|
|
14
|
+
import { createQueryFilterClosedInterval, createQueryFilterString } from "./queryFilter.ts";
|
|
15
|
+
|
|
16
|
+
export function createQueryFilterFixed(filter: ConfigFilterFixed, filterValue: FilterValueFixed): Query {
|
|
17
|
+
let query: Query;
|
|
18
|
+
switch (filter.id) {
|
|
19
|
+
case "fixed/chrom":
|
|
20
|
+
query = createQueryFilterString(["c"], filterValue as FilterValueChrom, false, false);
|
|
21
|
+
break;
|
|
22
|
+
case "fixed/pos":
|
|
23
|
+
query = createQueryFilterClosedInterval(["p"], filterValue as FilterValuePos);
|
|
24
|
+
break;
|
|
25
|
+
case "fixed/id":
|
|
26
|
+
query = createQueryFilterString(["i"], filterValue as FilterValueId, true, false);
|
|
27
|
+
break;
|
|
28
|
+
case "fixed/ref":
|
|
29
|
+
query = createQueryFilterString(["r"], filterValue as FilterValueRef, false, false);
|
|
30
|
+
break;
|
|
31
|
+
case "fixed/alt":
|
|
32
|
+
query = createQueryFilterString(["a"], filterValue as FilterValueAlt, true, false);
|
|
33
|
+
break;
|
|
34
|
+
case "fixed/qual":
|
|
35
|
+
query = createQueryFilterClosedInterval(["q"], filterValue as FilterValueQual);
|
|
36
|
+
break;
|
|
37
|
+
case "fixed/filter":
|
|
38
|
+
query = createQueryFilterString(["f"], filterValue as FilterValueFilter, true, false);
|
|
39
|
+
break;
|
|
40
|
+
default:
|
|
41
|
+
throw new UnexpectedEnumValueException(filter.id);
|
|
42
|
+
}
|
|
43
|
+
return query;
|
|
44
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { Query } from "@molgenis/vip-report-api";
|
|
2
|
+
import { SampleContainer } from "../api.ts";
|
|
3
|
+
import { createSelectorSample } from "./selector.ts";
|
|
4
|
+
import { ConfigVip } from "../../types/config";
|
|
5
|
+
import { FilterValueCategorical } from "../../types/configFilter";
|
|
6
|
+
import { createQueryFilterFieldCategorical } from "./queryFilterField.ts";
|
|
7
|
+
|
|
8
|
+
export function createQuerySample(config: ConfigVip, sample: SampleContainer): Query {
|
|
9
|
+
const filterValues = getFilterValues(config);
|
|
10
|
+
const selector = createSelectorSample(sample, config.filter_field);
|
|
11
|
+
return createQueryFilterFieldCategorical(selector, config.filter_field, filterValues);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
function getFilterValues(config: ConfigVip): FilterValueCategorical {
|
|
15
|
+
const filterSamplesClasses = config.params.vcf.filter_samples.classes.split(",");
|
|
16
|
+
// add null values to make query match with records that do not have a value for the field
|
|
17
|
+
return [...filterSamplesClasses, "__null"];
|
|
18
|
+
}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { Query, SelectorPart } from "@molgenis/vip-report-api";
|
|
2
|
+
import { VariantType } from "../variantType.ts";
|
|
3
|
+
import { UnexpectedEnumValueException } from "../error.ts";
|
|
4
|
+
import { createQueryComposed } from "./query.ts";
|
|
5
|
+
|
|
6
|
+
export function createQueryVariantType(variantType: VariantType): Query | null {
|
|
7
|
+
let query: Query | null;
|
|
8
|
+
switch (variantType.id) {
|
|
9
|
+
case "all":
|
|
10
|
+
query = null;
|
|
11
|
+
break;
|
|
12
|
+
case "snv":
|
|
13
|
+
query = createQueryVariantTypeSnv();
|
|
14
|
+
break;
|
|
15
|
+
case "str":
|
|
16
|
+
query = createQueryVariantTypeStr();
|
|
17
|
+
break;
|
|
18
|
+
case "sv":
|
|
19
|
+
query = createQueryVariantTypeSv();
|
|
20
|
+
break;
|
|
21
|
+
default:
|
|
22
|
+
throw new UnexpectedEnumValueException(variantType.id);
|
|
23
|
+
}
|
|
24
|
+
return query;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function createQueryVariantTypeSnv(): Query {
|
|
28
|
+
const queryParts: Query[] = [
|
|
29
|
+
{
|
|
30
|
+
selector: createSelectorVariantType(),
|
|
31
|
+
operator: "==",
|
|
32
|
+
args: null,
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
selector: createSelectorVariantType(),
|
|
36
|
+
operator: "==",
|
|
37
|
+
args: undefined,
|
|
38
|
+
},
|
|
39
|
+
];
|
|
40
|
+
return createQueryComposed(queryParts, "or");
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function createQueryVariantTypeStr(): Query {
|
|
44
|
+
return {
|
|
45
|
+
selector: createSelectorVariantType(),
|
|
46
|
+
operator: "==",
|
|
47
|
+
args: "STR",
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function createQueryVariantTypeSv(): Query {
|
|
52
|
+
return {
|
|
53
|
+
operator: "and",
|
|
54
|
+
args: [
|
|
55
|
+
{
|
|
56
|
+
selector: createSelectorVariantType(),
|
|
57
|
+
operator: "!=",
|
|
58
|
+
args: "STR",
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
selector: createSelectorVariantType(),
|
|
62
|
+
operator: "!=",
|
|
63
|
+
args: null,
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
selector: createSelectorVariantType(),
|
|
67
|
+
operator: "!=",
|
|
68
|
+
args: undefined,
|
|
69
|
+
},
|
|
70
|
+
],
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
function createSelectorVariantType(): SelectorPart[] {
|
|
75
|
+
return ["n", "SVTYPE"];
|
|
76
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { FieldMetadata } from "@molgenis/vip-report-vcf";
|
|
2
|
+
import { Selector, SelectorPart, SortPath } from "@molgenis/vip-report-api";
|
|
3
|
+
import { FieldMetadataWrapper } from "../vcf.ts";
|
|
4
|
+
import { SampleContainer } from "../api.ts";
|
|
5
|
+
|
|
6
|
+
export function createSelectorInfo(field: FieldMetadataWrapper): SelectorPart[] {
|
|
7
|
+
return ["n", ...selector(field)];
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export function createSelectorSample(sample: SampleContainer, field: FieldMetadataWrapper): SelectorPart[] {
|
|
11
|
+
return ["s", sample.item.data.index, ...selector(field)];
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export function createInfoSortPath(field: FieldMetadata): SortPath {
|
|
15
|
+
return ["n", ...selector(field).filter((part) => part !== "*")];
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
function selector(field: FieldMetadata): SelectorPart[] {
|
|
19
|
+
const selector: Selector = [];
|
|
20
|
+
let currentField: FieldMetadata | undefined = field;
|
|
21
|
+
do {
|
|
22
|
+
if (currentField.parent && currentField.parent.nested) {
|
|
23
|
+
const items = currentField.parent.nested.items;
|
|
24
|
+
let i;
|
|
25
|
+
for (i = 0; i < items.length; ++i) {
|
|
26
|
+
if (items[i]!.id === currentField.id) {
|
|
27
|
+
break;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
selector.push(i);
|
|
31
|
+
if (currentField.parent.number.count !== 1) {
|
|
32
|
+
selector.push("*");
|
|
33
|
+
}
|
|
34
|
+
} else {
|
|
35
|
+
selector.push(currentField.id);
|
|
36
|
+
}
|
|
37
|
+
currentField = currentField.parent;
|
|
38
|
+
} while (currentField);
|
|
39
|
+
selector.reverse();
|
|
40
|
+
return selector;
|
|
41
|
+
}
|