Skip to content

Commit

Permalink
Merge pull request #115 from molgenis/feat/sample_tree_categories
Browse files Browse the repository at this point in the history
Add sample decision tree categories
  • Loading branch information
dennishendriksen authored Nov 13, 2024
2 parents b0e8fbd + 7dd3220 commit ecfb27b
Show file tree
Hide file tree
Showing 4 changed files with 103 additions and 40 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@molgenis/vip-report-api",
"version": "6.0.1",
"version": "6.1.0",
"description": "TypeScript Report API for Variant Call Format (VCF) Report Templates",
"scripts": {
"build": "tsc --build",
Expand Down
45 changes: 45 additions & 0 deletions src/__tests__/apiClient.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,51 @@ beforeEach(() => {
api = new ApiClient(reportData as unknown as EncodedReport);
});

test("postProcess - sample tree categories", async () => {
const metadata = await api.getRecordsMeta();
expect(metadata.format["VIPC_S"].categories).toEqual({
U1: {
description: "Usable: probably",
label: "U1",
},
U2: {
description: "Usable: maybe",
label: "U2",
},
U3: {
description: "Usable: probably not",
label: "U3",
},
});
});

test("postProcess - decision tree categories", async () => {
const metadata = await api.getRecordsMeta();
const csqItems = metadata.info.CSQ?.nested?.items;
const csqItem = csqItems.find((item) => item.id === "VIPC");
expect(csqItem.categories).toEqual({
B: {
label: "B",
},
LB: {
label: "LB",
},
LP: {
label: "LP",
},
LQ: {
description: "Low quality variants.",
label: "LQ",
},
P: {
label: "P",
},
VUS: {
label: "VUS",
},
});
});

test("getAppMeta", async () => {
const metadata = await api.getAppMetadata();
expect(metadata).toEqual(
Expand Down
2 changes: 2 additions & 0 deletions src/__tests__/trio.vcf
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,11 @@
##INFO=<ID=n_string4,Number=1,Type=String,Description="n_string4">
##INFO=<ID=n_array0,Number=.,Type=String,Description="n_array0">
##INFO=<ID=n_object0,Number=.,Type=String,Description="Consequence annotations from Ensembl VEP. Format: n_string1|n_string2">
##INFO=<ID=CSQ,Number=.,Type=String,Description="Consequence annotations from Ensembl VEP. Format: Allele|VIPC">
##FORMAT=<ID=DP,Number=1,Type=String,Description="Depth">
##FORMAT=<ID=AD,Number=R,Type=Integer,Description="Allelic depths for the ref and alt alleles in the order listed">
##FORMAT=<ID=GT,Number=1,Type=String,Description="Genotype">
##FORMAT=<ID=VIPC_S,Number=.,Type=String,Description="VIP decision tree classification.">
#CHROM POS ID REF ALT QUAL FILTER INFO FORMAT Patient Mother Father
1 10042538 . C T . PASS n_array0=c,,d,b;n_number2=1;n_object0=dummy|c,dummy|,dummy|d,dummy|b;n_string0=a;n_string3=b;n_string4=b GT:DP:AD 1|0:50:45,5 0|0:10:10,0 0|0:10:10,0
1 16376412 . G A . PASS n_array0=b,c,a;n_bool3;n_bool6;n_bool7;n_number2=0;n_object0=dummy|b,dummy|c,dummy|a;n_string0=a;n_string3=a;n_string4=A GT:DP:AD 0|1:10:0,0 1|0:11:11,0 1|0:11:11,0
94 changes: 55 additions & 39 deletions src/apiClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -110,19 +110,10 @@ export class ApiClient implements Api {
}

private postProcessReportData(reportData: ReportData): ReportData {
if (!reportData.decisionTree) {
return reportData;
}
const csqItems = reportData.metadata.records.info.CSQ?.nested?.items;
if (!csqItems) {
return reportData;
}

// make VIPC categorical with categories based on tree exit nodes
const csqItem = csqItems.find((item) => item.id === "VIPC");
if (csqItem) {
csqItem.type = "CATEGORICAL";
csqItem.categories = Object.values(reportData.decisionTree.nodes)
// make VIPC_S categorical with categories based on sample tree exit nodes
const vipc_s = reportData.metadata.records.format["VIPC_S"];
if (vipc_s && reportData.sampleTree !== undefined) {
vipc_s.categories = Object.values(reportData.sampleTree.nodes)
.filter((node) => node.type === "LEAF")
.map((node) => node as LeafNode)
.reduce(
Expand All @@ -132,39 +123,64 @@ export class ApiClient implements Api {
}),
{},
);
csqItem.required = true;

vipc_s.type = "CATEGORICAL";
}

// make HPO categorical with categories based on phenotypes
const hpoItem = csqItems.find((item) => item.id === "HPO");
if (hpoItem) {
const categories = reportData.data.phenotypes
? (reportData.data.phenotypes as Phenotype[])
.flatMap((phenotype) => phenotype.phenotypicFeaturesList)
.map((phenotype) => phenotype.type.id)
.filter((v, i, a) => a.indexOf(v) === i)
.sort()
: [];
if (categories.length > 0) {
hpoItem.type = "CATEGORICAL";
const categories: CategoryRecord = (reportData.data.phenotypes as Phenotype[])
.flatMap((phenotype) => phenotype.phenotypicFeaturesList)
.reduce(
(acc, phenotype) => ({
...acc,
[phenotype.type.id]: { label: phenotype.type.label },
}),
{},
);
hpoItem.categories = Object.keys(categories)
.sort()
const csqItems = reportData.metadata.records.info.CSQ?.nested?.items;
if (!csqItems) {
return reportData;
}

// make VIPC categorical with categories based on tree exit nodes
const csqItem = csqItems.find((item) => item.id === "VIPC");
if (csqItem) {
if (reportData.decisionTree) {
csqItem.type = "CATEGORICAL";
csqItem.categories = Object.values(reportData.decisionTree.nodes)
.filter((node) => node.type === "LEAF")
.map((node) => node as LeafNode)
.reduce(
(acc, categoryId) => ({
(acc, node) => ({
...acc,
[categoryId]: categories[categoryId],
[node.class]: { label: node.class, description: node.description },
}),
{},
);
csqItem.required = true;
}

// make HPO categorical with categories based on phenotypes
const hpoItem = csqItems.find((item) => item.id === "HPO");
if (hpoItem) {
const categories = reportData.data.phenotypes
? (reportData.data.phenotypes as Phenotype[])
.flatMap((phenotype) => phenotype.phenotypicFeaturesList)
.map((phenotype) => phenotype.type.id)
.filter((v, i, a) => a.indexOf(v) === i)
.sort()
: [];
if (categories.length > 0) {
hpoItem.type = "CATEGORICAL";
const categories: CategoryRecord = (reportData.data.phenotypes as Phenotype[])
.flatMap((phenotype) => phenotype.phenotypicFeaturesList)
.reduce(
(acc, phenotype) => ({
...acc,
[phenotype.type.id]: { label: phenotype.type.label },
}),
{},
);
hpoItem.categories = Object.keys(categories)
.sort()
.reduce(
(acc, categoryId) => ({
...acc,
[categoryId]: categories[categoryId],
}),
{},
);
}
}
}

Expand Down

0 comments on commit ecfb27b

Please sign in to comment.