From b9e137605ff70f060ad79f28244b928bd1badf40 Mon Sep 17 00:00:00 2001 From: Caralyn Reisle Date: Thu, 15 Apr 2021 15:37:16 -0700 Subject: [PATCH 01/23] Add link to main PORI repo --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 5e0de327..377852f4 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,8 @@ ![build](https://github.com/bcgsc/pori_graphkb_loader/workflows/build/badge.svg?branch=master) ![Docker Image Version (latest semver)](https://img.shields.io/docker/v/bcgsc/pori-graphkb-loader?label=docker%20image) ![node versions](https://img.shields.io/badge/node-10%20%7C%2012%20%7C%2014-blue) +This repository is part of the [platform for oncogenomic reporting and interpretation](https://github.com/bcgsc/pori). + This package is used to import content from a variety of sources into GraphKB using the API. - [Loaders](#loaders) From 9adc76aff55289ce421b4cfbae7c7f3a0670456c Mon Sep 17 00:00:00 2001 From: Caralyn Reisle Date: Fri, 16 Apr 2021 11:39:56 -0700 Subject: [PATCH 02/23] Improve doc strings --- src/civic/index.js | 1 + src/civic/variant.js | 4 ++- src/graphkb.js | 59 ++++++++++++++++++++++++++++++++++++++------ 3 files changed, 56 insertions(+), 8 deletions(-) diff --git a/src/civic/index.js b/src/civic/index.js index 01fb22af..346032c4 100644 --- a/src/civic/index.js +++ b/src/civic/index.js @@ -682,6 +682,7 @@ const upload = async (opt) => { const oneToOne = mappedCount === 1 && preupload.size === 1; + // upload all GraphKB statements for this CIViC Evidence Item for (const record of recordList) { for (const variant of record.variants) { for (const drugs of record.drugs) { diff --git a/src/civic/variant.js b/src/civic/variant.js index f55ec0b7..df131f3e 100644 --- a/src/civic/variant.js +++ b/src/civic/variant.js @@ -133,6 +133,7 @@ const normalizeVariantRecord = ({ type: name.replace(/-/g, ' '), }]; } if (match = /^t\(([^;()]+);([^;()]+)\)\(([^;()]+);([^;()]+)\)$/i.exec(name)) { + // convert translocation syntax const [, chr1, chr2, pos1, pos2] = match; return [{ positional: true, @@ -141,6 +142,7 @@ const normalizeVariantRecord = ({ variant: `translocation(${pos1}, ${pos2})`, }]; } if (match = /^(p\.)?([a-z*]\d+\S*)\s+\((c\.[^)]+)\)$/i.exec(name)) { + // split combined protein + cds notation let [, , protein, cds] = match; // correct deprecated cds syntac @@ -152,7 +154,7 @@ const normalizeVariantRecord = ({ } } return [{ - inferredBy: [ + inferredBy: [ // keep the cds variant as a link to the protein variant { positional: true, reference1: { ...referenceGene }, diff --git a/src/graphkb.js b/src/graphkb.js index 18b8358d..55d66247 100644 --- a/src/graphkb.js +++ b/src/graphkb.js @@ -45,7 +45,14 @@ const simplifyRecordsLinks = (content, level = 0) => { return content; }; - +/** + * Check if things have changed and we should send an update request + * + * @param {string|ClassModel} modelIn the model name or model object this record belongs to + * @param {Object} originalContentIn the original record + * @param {Object} newContentIn the new record + * @param {string[]} upsertCheckExclude a list of properties to ignore changes in + */ const shouldUpdate = (modelIn, originalContentIn, newContentIn, upsertCheckExclude = []) => { const model = typeof modelIn === 'string' ? schema.get(modelIn) @@ -290,6 +297,15 @@ class ApiConnection { return created; } + /** + * Given some query, fetch all matching records (handles paginating over large queries) + * @param {Object} opt + * @param {Object} opt.filters query filters + * @param {string} opt.target the target class to be queried + * @param {Number} opt.limit maximum number of records to fetch per request + * @param {Number} opt.neighbors maximum record depth to fetch + * @param {string[]} opt.returnProperties properties to return from each record + */ async getRecords(opt) { const { filters, @@ -333,11 +349,16 @@ class ApiConnection { } /** + * Fetch a record with a query. Error if the record cannot be uniquely identified. * - * @param {object} opt - * @param {object} opt.filters the conditions/query parameters for the selection - * @param {string} opt.target the target to query - * @param {function} opt.sort the function to use in sorting if multiple results are found + * @param {Object} opt + * @param {Object} opt.filters query filters + * @param {string} opt.target the target class to be queried + * @param {Number} opt.limit maximum number of records to fetch per request + * @param {Number} opt.neighbors maximum record depth to fetch + * @param {function} opt.sort the comparator function to use in sorting if multiple results are found + * + * @throws on multiple records matching the query that do not have a non-zero sort comparison value */ async getUniqueRecordBy(opt) { const { @@ -367,6 +388,9 @@ class ApiConnection { /** * Fetch therapy by name, ignore plurals for some cases + * + * @param {string} term the name or sourceId of the therapeutic term + * @param {string} source the source record ID the therapy is expected to belong to */ async getTherapy(term, source) { let error, @@ -421,6 +445,10 @@ class ApiConnection { throw error; } + /** + * @param {string} term the name of the vocabulary term to be fetched + * @param {string} sourceName the name of the source the vocabulary term belongs to + */ async getVocabularyTerm(term, sourceName = INTERNAL_SOURCE_NAME) { if (!term) { throw new Error('Cannot fetch vocabulary for empty term name'); @@ -452,6 +480,12 @@ class ApiConnection { return result; } + /** + * This will soft-delete a record via the API + * + * @param {string} target the class this record belongs to + * @param {string} recordId the ID of the record being deleted + */ async deleteRecord(target, recordId) { const model = schema.get(target); const { result } = jc.retrocycle(await this.request({ @@ -540,8 +574,8 @@ class ApiConnection { /** * @param {object} opt - * @param {object} opt.content - * @param {string} opt.target + * @param {object} opt.content the content of the variant record + * @param {string} opt.target the class to add the record to (PositionalVariant or CategoryVariant) */ async addVariant(opt) { const { @@ -574,6 +608,17 @@ class ApiConnection { }); } + /** + * Add a therapy combination. Will split the input name by "+" and query to find individual + * components. These will they be used to create the combination record + * + * TODO: link elements to combination therapy + * + * @param {string|Object} source the source record ID or source record this therapy belongs to + * @param {string} therapyName the name of the therpeutic combination + * @param {Object} opt + * @param {boolean} opt.matchSource flag to indicate sub-components of the therapy must be from the same source + */ async addTherapyCombination(source, therapyName, opt = {}) { const { matchSource = false } = opt; From a1cd83117693f3591549852e32a40d81d76eafad Mon Sep 17 00:00:00 2001 From: Caralyn Reisle Date: Wed, 5 May 2021 15:48:22 -0700 Subject: [PATCH 03/23] Add tests for translateRelevance --- package-lock.json | 41 ++++++++++++----- src/civic/index.js | 112 +++++++++++++++++++++++---------------------- test/civic.test.js | 30 +++++++++++- 3 files changed, 117 insertions(+), 66 deletions(-) diff --git a/package-lock.json b/package-lock.json index 1096b450..75073f36 100644 --- a/package-lock.json +++ b/package-lock.json @@ -887,7 +887,8 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", - "dev": true + "dev": true, + "optional": true }, "supports-color": { "version": "7.1.0", @@ -4115,7 +4116,8 @@ "ansi-regex": { "version": "2.1.1", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "aproba": { "version": "1.2.0", @@ -4158,7 +4160,8 @@ "code-point-at": { "version": "1.1.0", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "concat-map": { "version": "0.0.1", @@ -4169,7 +4172,8 @@ "console-control-strings": { "version": "1.1.0", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "core-util-is": { "version": "1.0.2", @@ -4286,7 +4290,8 @@ "inherits": { "version": "2.0.4", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "ini": { "version": "1.3.5", @@ -4298,6 +4303,7 @@ "version": "1.0.0", "bundled": true, "dev": true, + "optional": true, "requires": { "number-is-nan": "^1.0.0" } @@ -4320,12 +4326,14 @@ "minimist": { "version": "1.2.5", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "minipass": { "version": "2.9.0", "bundled": true, "dev": true, + "optional": true, "requires": { "safe-buffer": "^5.1.2", "yallist": "^3.0.0" @@ -4344,6 +4352,7 @@ "version": "0.5.3", "bundled": true, "dev": true, + "optional": true, "requires": { "minimist": "^1.2.5" } @@ -4434,7 +4443,8 @@ "number-is-nan": { "version": "1.0.1", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "object-assign": { "version": "4.1.1", @@ -4446,6 +4456,7 @@ "version": "1.4.0", "bundled": true, "dev": true, + "optional": true, "requires": { "wrappy": "1" } @@ -4523,7 +4534,8 @@ "safe-buffer": { "version": "5.1.2", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "safer-buffer": { "version": "2.1.2", @@ -4559,6 +4571,7 @@ "version": "1.0.2", "bundled": true, "dev": true, + "optional": true, "requires": { "code-point-at": "^1.0.0", "is-fullwidth-code-point": "^1.0.0", @@ -4578,6 +4591,7 @@ "version": "3.0.1", "bundled": true, "dev": true, + "optional": true, "requires": { "ansi-regex": "^2.0.0" } @@ -4621,12 +4635,14 @@ "wrappy": { "version": "1.0.2", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "yallist": { "version": "3.1.1", "bundled": true, - "dev": true + "dev": true, + "optional": true } } }, @@ -5010,6 +5026,7 @@ "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.2.1.tgz", "integrity": "sha512-6e1q1cnWP2RXD9/keSkxHScg508CdXqXWgWBaETNhyuBFz+kUZlKboh+ISK+bU++DmbHimVBrOz/zzPe0sZ3sQ==", "dev": true, + "optional": true, "requires": { "parent-module": "^1.0.0", "resolve-from": "^4.0.0" @@ -5019,7 +5036,8 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", - "dev": true + "dev": true, + "optional": true } } }, @@ -8546,6 +8564,7 @@ "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", "dev": true, + "optional": true, "requires": { "callsites": "^3.0.0" } diff --git a/src/civic/index.js b/src/civic/index.js index 346032c4..e8db3783 100644 --- a/src/civic/index.js +++ b/src/civic/index.js @@ -112,78 +112,81 @@ const validateEvidenceSpec = ajv.compile({ /** - * Convert the CIViC relevance types to GraphKB terms + * Extract the appropriate GraphKB relevance term from a CIViC evidence record */ -const getRelevance = async ({ rawRecord, conn }) => { - const translateRelevance = ({ evidenceType, clinicalSignificance, evidenceDirection }) => { - switch (evidenceType) { // eslint-disable-line default-case - case 'Predictive': { - switch (clinicalSignificance) { // eslint-disable-line default-case - case 'Sensitivity': - case 'Adverse Response': - case 'Reduced Sensitivity': - - case 'Resistance': { - return clinicalSignificance.toLowerCase(); - } - - case 'Sensitivity/Response': { return 'sensitivity'; } +const translateRelevance = (evidenceType, evidenceDirection, clinicalSignificance) => { + switch (evidenceType) { // eslint-disable-line default-case + case 'Predictive': { + switch (clinicalSignificance) { // eslint-disable-line default-case + case 'Sensitivity': + case 'Adverse Response': + case 'Reduced Sensitivity': + + case 'Resistance': { + return clinicalSignificance.toLowerCase(); } - break; - } - case 'Functional': { - return clinicalSignificance.toLowerCase(); + case 'Sensitivity/Response': { return 'sensitivity'; } } + break; + } - case 'Diagnostic': { - switch (clinicalSignificance) { // eslint-disable-line default-case - case 'Positive': { return 'favours diagnosis'; } + case 'Functional': { + return clinicalSignificance.toLowerCase(); + } - case 'Negative': { return 'opposes diagnosis'; } - } - break; + case 'Diagnostic': { + switch (clinicalSignificance) { // eslint-disable-line default-case + case 'Positive': { return 'favours diagnosis'; } + + case 'Negative': { return 'opposes diagnosis'; } } + break; + } - case 'Prognostic': { - switch (clinicalSignificance) { // eslint-disable-line default-case - case 'Negative': + case 'Prognostic': { + switch (clinicalSignificance) { // eslint-disable-line default-case + case 'Negative': - case 'Poor Outcome': { - return 'unfavourable prognosis'; - } - case 'Positive': + case 'Poor Outcome': { + return 'unfavourable prognosis'; + } + case 'Positive': - case 'Better Outcome': { - return 'favourable prognosis'; - } + case 'Better Outcome': { + return 'favourable prognosis'; } - break; } + break; + } - case 'Predisposing': { - if (['Positive', null, 'null'].includes(clinicalSignificance)) { - return 'Predisposing'; - } if (clinicalSignificance.includes('Pathogenic')) { - return clinicalSignificance; - } if (clinicalSignificance === 'Uncertain Significance') { - return 'likely predisposing'; - } - break; + case 'Predisposing': { + if (['Positive', null, 'null'].includes(clinicalSignificance)) { + return 'predisposing'; + } if (clinicalSignificance.includes('Pathogenic')) { + return clinicalSignificance.toLowerCase(); + } if (clinicalSignificance === 'Uncertain Significance') { + return 'likely predisposing'; } + break; } + } - throw new Error( - `unable to process relevance (${JSON.stringify({ clinicalSignificance, evidenceDirection, evidenceType })})`, - ); - }; + throw new Error( + `unable to process relevance (${JSON.stringify({ clinicalSignificance, evidenceDirection, evidenceType })})`, + ); +}; +/** + * Convert the CIViC relevance types to GraphKB terms + */ +const getRelevance = async ({ rawRecord, conn }) => { // translate the type to a GraphKB vocabulary term - let relevance = translateRelevance({ - clinicalSignificance: rawRecord.clinical_significance, - evidenceDirection: rawRecord.evidence_direction, - evidenceType: rawRecord.evidence_type, - }).toLowerCase(); + let relevance = translateRelevance( + rawRecord.evidence_type, + rawRecord.evidence_direction, + rawRecord.clinical_significance, + ).toLowerCase(); if (RELEVANCE_CACHE[relevance] === undefined) { relevance = await conn.getVocabularyTerm(relevance); @@ -739,5 +742,6 @@ const upload = async (opt) => { module.exports = { SOURCE_DEFN, specs: { validateEvidenceSpec }, + translateRelevance, upload, }; diff --git a/test/civic.test.js b/test/civic.test.js index dab721c1..2662ff3a 100644 --- a/test/civic.test.js +++ b/test/civic.test.js @@ -1,5 +1,5 @@ const { normalizeVariantRecord } = require('../src/civic/variant'); - +const { translateRelevance } = require('../src/civic'); describe('normalizeVariantRecord', () => { test('exon mutation', () => { @@ -615,3 +615,31 @@ describe('normalizeVariantRecord', () => { }); }); }); + +describe('translateRelevance', () => { + test.each([ + ['Predictive', 'Supports', 'Sensitivity', 'sensitivity'], + ['Predictive', 'Supports', 'Adverse Response', 'adverse response'], + ['Predictive', 'Supports', 'Reduced Sensitivity', 'reduced sensitivity'], + ['Predictive', 'Supports', 'Resistance', 'resistance'], + ['Predictive', 'Supports', 'Sensitivity/Response', 'sensitivity'], + ['Diagnostic', 'Supports', 'Positive', 'favours diagnosis'], + ['Diagnostic', 'Supports', 'Negative', 'opposes diagnosis'], + ['Prognostic', 'Supports', 'Negative', 'unfavourable prognosis'], + ['Prognostic', 'Supports', 'Poor Outcome', 'unfavourable prognosis'], + ['Prognostic', 'Supports', 'Positive', 'favourable prognosis'], + ['Prognostic', 'Supports', 'Better Outcome', 'favourable prognosis'], + ['Predisposing', 'Supports', 'Positive', 'predisposing'], + ['Predisposing', 'Supports', null, 'predisposing'], + ['Predisposing', 'Supports', 'null', 'predisposing'], + ['Predisposing', 'Supports', 'Pathogenic', 'pathogenic'], + ['Predisposing', 'Supports', 'Likely Pathogenic', 'likely pathogenic'], + ['Functional', 'Supports', 'Gain of Function', 'gain of function'], + // ['Predictive', 'Does not Support', 'Sensitivity', 'no response'], + // ['Predictive', 'Does not Support', 'Sensitivity/Response', 'no response'], + ])( + '%s|%s|%s returns %s', (evidenceType, evidenceDirection, clinicalSignificance, expected) => { + expect(translateRelevance(evidenceType, evidenceDirection, clinicalSignificance)).toEqual(expected); + }, + ); +}); From 4dd85092c29ab30886fa76a0d4a24def6f63cde3 Mon Sep 17 00:00:00 2001 From: Cam Grisdale Date: Thu, 20 May 2021 10:45:03 -0700 Subject: [PATCH 04/23] Un-comment Predictive Does not Support test lines --- test/civic.test.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/civic.test.js b/test/civic.test.js index 2662ff3a..9912a894 100644 --- a/test/civic.test.js +++ b/test/civic.test.js @@ -635,8 +635,8 @@ describe('translateRelevance', () => { ['Predisposing', 'Supports', 'Pathogenic', 'pathogenic'], ['Predisposing', 'Supports', 'Likely Pathogenic', 'likely pathogenic'], ['Functional', 'Supports', 'Gain of Function', 'gain of function'], - // ['Predictive', 'Does not Support', 'Sensitivity', 'no response'], - // ['Predictive', 'Does not Support', 'Sensitivity/Response', 'no response'], + ['Predictive', 'Does not Support', 'Sensitivity', 'no response'], + ['Predictive', 'Does not Support', 'Sensitivity/Response', 'no response'], ])( '%s|%s|%s returns %s', (evidenceType, evidenceDirection, clinicalSignificance, expected) => { expect(translateRelevance(evidenceType, evidenceDirection, clinicalSignificance)).toEqual(expected); From 5335480c2bc337f38102de4cbda3245839e86b47 Mon Sep 17 00:00:00 2001 From: Cam Grisdale Date: Thu, 20 May 2021 11:06:01 -0700 Subject: [PATCH 05/23] modify translateRelevance to support Does Not Support Sensitivity --- src/civic/index.js | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/civic/index.js b/src/civic/index.js index e8db3783..4c0b5d05 100644 --- a/src/civic/index.js +++ b/src/civic/index.js @@ -119,6 +119,11 @@ const translateRelevance = (evidenceType, evidenceDirection, clinicalSignificanc case 'Predictive': { switch (clinicalSignificance) { // eslint-disable-line default-case case 'Sensitivity': + switch (evidenceDirection) { + case 'Does Not Support': { return 'no response'; } + case 'Supports': { return clinicalSignificance.toLowerCase(); } + } + case 'Adverse Response': case 'Reduced Sensitivity': @@ -126,7 +131,12 @@ const translateRelevance = (evidenceType, evidenceDirection, clinicalSignificanc return clinicalSignificance.toLowerCase(); } - case 'Sensitivity/Response': { return 'sensitivity'; } + case 'Sensitivity/Response': + switch (evidenceDirection) { + case 'Does Not Support': { return 'no response'; } + case 'Supports': { return 'sensitivity'; } + } + } break; } From e0824185dc2b0cb82bbe68e924c2da7c99714918 Mon Sep 17 00:00:00 2001 From: Cam Grisdale Date: Thu, 20 May 2021 11:13:09 -0700 Subject: [PATCH 06/23] fixing eslint errors --- src/civic/index.js | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/civic/index.js b/src/civic/index.js index 4c0b5d05..d564edc2 100644 --- a/src/civic/index.js +++ b/src/civic/index.js @@ -119,24 +119,21 @@ const translateRelevance = (evidenceType, evidenceDirection, clinicalSignificanc case 'Predictive': { switch (clinicalSignificance) { // eslint-disable-line default-case case 'Sensitivity': - switch (evidenceDirection) { + switch (evidenceDirection) { // eslint-disable-line default-case case 'Does Not Support': { return 'no response'; } case 'Supports': { return clinicalSignificance.toLowerCase(); } } - case 'Adverse Response': case 'Reduced Sensitivity': case 'Resistance': { return clinicalSignificance.toLowerCase(); } - case 'Sensitivity/Response': - switch (evidenceDirection) { + switch (evidenceDirection) { // eslint-disable-line default-case case 'Does Not Support': { return 'no response'; } case 'Supports': { return 'sensitivity'; } } - } break; } From 5747295ec35e7a3aaa5284054fd0bdf952a1348d Mon Sep 17 00:00:00 2001 From: Cam Grisdale Date: Thu, 20 May 2021 11:43:10 -0700 Subject: [PATCH 07/23] missing parentheses --- src/civic/index.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/civic/index.js b/src/civic/index.js index d564edc2..692f69bf 100644 --- a/src/civic/index.js +++ b/src/civic/index.js @@ -118,22 +118,24 @@ const translateRelevance = (evidenceType, evidenceDirection, clinicalSignificanc switch (evidenceType) { // eslint-disable-line default-case case 'Predictive': { switch (clinicalSignificance) { // eslint-disable-line default-case - case 'Sensitivity': + case 'Sensitivity': { switch (evidenceDirection) { // eslint-disable-line default-case case 'Does Not Support': { return 'no response'; } case 'Supports': { return clinicalSignificance.toLowerCase(); } } + } case 'Adverse Response': case 'Reduced Sensitivity': case 'Resistance': { return clinicalSignificance.toLowerCase(); } - case 'Sensitivity/Response': + case 'Sensitivity/Response': { switch (evidenceDirection) { // eslint-disable-line default-case case 'Does Not Support': { return 'no response'; } case 'Supports': { return 'sensitivity'; } } + } } break; } From ecbdcd3b918b2ba08e246cc8534f181c6be178ee Mon Sep 17 00:00:00 2001 From: Cam Grisdale Date: Thu, 20 May 2021 11:57:08 -0700 Subject: [PATCH 08/23] missing blank lines --- src/civic/index.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/civic/index.js b/src/civic/index.js index 692f69bf..4fde141f 100644 --- a/src/civic/index.js +++ b/src/civic/index.js @@ -121,10 +121,12 @@ const translateRelevance = (evidenceType, evidenceDirection, clinicalSignificanc case 'Sensitivity': { switch (evidenceDirection) { // eslint-disable-line default-case case 'Does Not Support': { return 'no response'; } + case 'Supports': { return clinicalSignificance.toLowerCase(); } } } case 'Adverse Response': + case 'Reduced Sensitivity': case 'Resistance': { @@ -133,6 +135,7 @@ const translateRelevance = (evidenceType, evidenceDirection, clinicalSignificanc case 'Sensitivity/Response': { switch (evidenceDirection) { // eslint-disable-line default-case case 'Does Not Support': { return 'no response'; } + case 'Supports': { return 'sensitivity'; } } } From a4f0aad567c7b669124733909624312bc05596f1 Mon Sep 17 00:00:00 2001 From: Cam Grisdale Date: Thu, 20 May 2021 14:37:08 -0700 Subject: [PATCH 09/23] missing blank line --- src/civic/index.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/civic/index.js b/src/civic/index.js index 4fde141f..4ce2fa7d 100644 --- a/src/civic/index.js +++ b/src/civic/index.js @@ -132,6 +132,7 @@ const translateRelevance = (evidenceType, evidenceDirection, clinicalSignificanc case 'Resistance': { return clinicalSignificance.toLowerCase(); } + case 'Sensitivity/Response': { switch (evidenceDirection) { // eslint-disable-line default-case case 'Does Not Support': { return 'no response'; } From 5c1d291a8c81bde330f5d84134c117989b62eede Mon Sep 17 00:00:00 2001 From: Cam Grisdale Date: Thu, 20 May 2021 15:13:50 -0700 Subject: [PATCH 10/23] fixing title case for Does Not Support --- test/civic.test.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/civic.test.js b/test/civic.test.js index 9912a894..1d5d59ba 100644 --- a/test/civic.test.js +++ b/test/civic.test.js @@ -635,8 +635,8 @@ describe('translateRelevance', () => { ['Predisposing', 'Supports', 'Pathogenic', 'pathogenic'], ['Predisposing', 'Supports', 'Likely Pathogenic', 'likely pathogenic'], ['Functional', 'Supports', 'Gain of Function', 'gain of function'], - ['Predictive', 'Does not Support', 'Sensitivity', 'no response'], - ['Predictive', 'Does not Support', 'Sensitivity/Response', 'no response'], + ['Predictive', 'Does Not Support', 'Sensitivity', 'no response'], + ['Predictive', 'Does Not Support', 'Sensitivity/Response', 'no response'], ])( '%s|%s|%s returns %s', (evidenceType, evidenceDirection, clinicalSignificance, expected) => { expect(translateRelevance(evidenceType, evidenceDirection, clinicalSignificance)).toEqual(expected); From 798b077848649b7d1b5b389c1668794d264ace59 Mon Sep 17 00:00:00 2001 From: Cam Grisdale Date: Tue, 25 May 2021 14:23:37 -0700 Subject: [PATCH 11/23] add fusion exon example --- test/civic.test.js | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/test/civic.test.js b/test/civic.test.js index 1d5d59ba..e9883995 100644 --- a/test/civic.test.js +++ b/test/civic.test.js @@ -258,6 +258,25 @@ describe('normalizeVariantRecord', () => { ]); }); + test('fusion with new exon position notation', () => { + // EML4-ALK e20-e20 + // ALK FUSIONS + const variants = normalizeVariantRecord({ + entrezId: 1, + entrezName: 'ALK', + name: 'EML4-ALK e20-e20', + }); + expect(variants).toEqual([ + { + positional: true, + reference1: { name: 'eml4' }, + reference2: { name: 'alk', sourceId: '1' }, + variant: 'fusion(e.20,e.20)', + }, + ]); + }); + + test('fusion with reference2 input gene', () => { // EML4-ALK E20;A20 // ALK FUSIONS From cb4e0aab758fa7c028bb03f183db9dbbfa492d8b Mon Sep 17 00:00:00 2001 From: Cam Grisdale Date: Tue, 25 May 2021 15:25:59 -0700 Subject: [PATCH 12/23] reverting fusion exon example --- test/civic.test.js | 19 ------------------- 1 file changed, 19 deletions(-) diff --git a/test/civic.test.js b/test/civic.test.js index e9883995..1d5d59ba 100644 --- a/test/civic.test.js +++ b/test/civic.test.js @@ -258,25 +258,6 @@ describe('normalizeVariantRecord', () => { ]); }); - test('fusion with new exon position notation', () => { - // EML4-ALK e20-e20 - // ALK FUSIONS - const variants = normalizeVariantRecord({ - entrezId: 1, - entrezName: 'ALK', - name: 'EML4-ALK e20-e20', - }); - expect(variants).toEqual([ - { - positional: true, - reference1: { name: 'eml4' }, - reference2: { name: 'alk', sourceId: '1' }, - variant: 'fusion(e.20,e.20)', - }, - ]); - }); - - test('fusion with reference2 input gene', () => { // EML4-ALK E20;A20 // ALK FUSIONS From 88ddf828481a17779cfc0841163e40eaff525337 Mon Sep 17 00:00:00 2001 From: Cam Grisdale Date: Fri, 28 May 2021 13:51:16 -0700 Subject: [PATCH 13/23] comment out skipping Does Not Support --- src/civic/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/civic/index.js b/src/civic/index.js index 4ce2fa7d..b3c2d17d 100644 --- a/src/civic/index.js +++ b/src/civic/index.js @@ -588,7 +588,7 @@ const downloadEvidenceRecords = async (baseUrl) => { if ( record.clinical_significance === 'N/A' - || record.evidence_direction === 'Does Not Support' +// || record.evidence_direction === 'Does Not Support' || (record.clinical_significance === null && record.evidence_type === 'Predictive') ) { counts.skip++; From 808f7a8bf19eab695b53b8a7ce7a2114641db4cd Mon Sep 17 00:00:00 2001 From: Cam Grisdale Date: Fri, 28 May 2021 13:57:28 -0700 Subject: [PATCH 14/23] fixing eslint error --- src/civic/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/civic/index.js b/src/civic/index.js index b3c2d17d..b8fe6072 100644 --- a/src/civic/index.js +++ b/src/civic/index.js @@ -588,7 +588,7 @@ const downloadEvidenceRecords = async (baseUrl) => { if ( record.clinical_significance === 'N/A' -// || record.evidence_direction === 'Does Not Support' + //|| record.evidence_direction === 'Does Not Support' || (record.clinical_significance === null && record.evidence_type === 'Predictive') ) { counts.skip++; From 27ecdbdaa2f95f27ae43a3efe48e6d68247ffc4e Mon Sep 17 00:00:00 2001 From: Cam Grisdale Date: Fri, 28 May 2021 14:12:07 -0700 Subject: [PATCH 15/23] fixing eslint error space --- src/civic/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/civic/index.js b/src/civic/index.js index b8fe6072..3cfda653 100644 --- a/src/civic/index.js +++ b/src/civic/index.js @@ -588,7 +588,7 @@ const downloadEvidenceRecords = async (baseUrl) => { if ( record.clinical_significance === 'N/A' - //|| record.evidence_direction === 'Does Not Support' + // || record.evidence_direction === 'Does Not Support' || (record.clinical_significance === null && record.evidence_type === 'Predictive') ) { counts.skip++; From b202acb3bbb81ad31a8ac323d148d7fd32c7fc38 Mon Sep 17 00:00:00 2001 From: Cam Grisdale Date: Wed, 2 Jun 2021 17:31:42 -0700 Subject: [PATCH 16/23] modify order of if/switch blocks for Predictive --- src/civic/index.js | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/src/civic/index.js b/src/civic/index.js index 3cfda653..3395ac81 100644 --- a/src/civic/index.js +++ b/src/civic/index.js @@ -117,31 +117,32 @@ const validateEvidenceSpec = ajv.compile({ const translateRelevance = (evidenceType, evidenceDirection, clinicalSignificance) => { switch (evidenceType) { // eslint-disable-line default-case case 'Predictive': { - switch (clinicalSignificance) { // eslint-disable-line default-case - case 'Sensitivity': { - switch (evidenceDirection) { // eslint-disable-line default-case - case 'Does Not Support': { return 'no response'; } + if (evidenceDirection == 'Does Not Support') { + switch (clinicalSignificance) { // eslint-disable-line default-case + case 'Sensitivity': - case 'Supports': { return clinicalSignificance.toLowerCase(); } + case 'Sensitivity/Response': { + return 'no response'; } } - case 'Adverse Response': - - case 'Reduced Sensitivity': - - case 'Resistance': { - return clinicalSignificance.toLowerCase(); - } - case 'Sensitivity/Response': { - switch (evidenceDirection) { // eslint-disable-line default-case - case 'Does Not Support': { return 'no response'; } + } else if (evidenceDirection == 'Supports') { + switch (clinicalSignificance) { // eslint-disable-line default-case + case 'Sensitivity': + case 'Adverse Response': + case 'Reduced Sensitivity': - case 'Supports': { return 'sensitivity'; } + case 'Resistance': { + return clinicalSignificance.toLowerCase(); } + + case 'Sensitivity/Response': { return 'sensitivity'; } } } - break; + + throw new Error( + `unable to process relevance (${JSON.stringify({ clinicalSignificance, evidenceDirection, evidenceType })})`, + ); } case 'Functional': { @@ -588,7 +589,6 @@ const downloadEvidenceRecords = async (baseUrl) => { if ( record.clinical_significance === 'N/A' - // || record.evidence_direction === 'Does Not Support' || (record.clinical_significance === null && record.evidence_type === 'Predictive') ) { counts.skip++; From bbfa2a5641aaecccf864aa0b31bdf7b49baba01b Mon Sep 17 00:00:00 2001 From: Cam Grisdale Date: Wed, 2 Jun 2021 17:37:31 -0700 Subject: [PATCH 17/23] fixing eslint errors line 120 and 129 --- src/civic/index.js | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/civic/index.js b/src/civic/index.js index 3395ac81..adae8712 100644 --- a/src/civic/index.js +++ b/src/civic/index.js @@ -117,7 +117,7 @@ const validateEvidenceSpec = ajv.compile({ const translateRelevance = (evidenceType, evidenceDirection, clinicalSignificance) => { switch (evidenceType) { // eslint-disable-line default-case case 'Predictive': { - if (evidenceDirection == 'Does Not Support') { + if (evidenceDirection === 'Does Not Support') { switch (clinicalSignificance) { // eslint-disable-line default-case case 'Sensitivity': @@ -125,8 +125,7 @@ const translateRelevance = (evidenceType, evidenceDirection, clinicalSignificanc return 'no response'; } } - - } else if (evidenceDirection == 'Supports') { + } else if (evidenceDirection === 'Supports') { switch (clinicalSignificance) { // eslint-disable-line default-case case 'Sensitivity': case 'Adverse Response': From bd747e7f9429c341db13c6912aa5b64e395aac61 Mon Sep 17 00:00:00 2001 From: Cam Grisdale Date: Thu, 3 Jun 2021 14:59:59 -0700 Subject: [PATCH 18/23] replace throw error with a break --- src/civic/index.js | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/civic/index.js b/src/civic/index.js index adae8712..4882e6e3 100644 --- a/src/civic/index.js +++ b/src/civic/index.js @@ -138,10 +138,7 @@ const translateRelevance = (evidenceType, evidenceDirection, clinicalSignificanc case 'Sensitivity/Response': { return 'sensitivity'; } } } - - throw new Error( - `unable to process relevance (${JSON.stringify({ clinicalSignificance, evidenceDirection, evidenceType })})`, - ); + break; } case 'Functional': { From 533210f46439329610ad5e32e9d896af4fbb8980 Mon Sep 17 00:00:00 2001 From: Cam Grisdale Date: Mon, 7 Jun 2021 11:16:05 -0700 Subject: [PATCH 19/23] add test for new civic exon notation and modify regex --- src/civic/variant.js | 2 +- test/civic.test.js | 18 ++++++++++++++++++ 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/src/civic/variant.js b/src/civic/variant.js index df131f3e..5117010e 100644 --- a/src/civic/variant.js +++ b/src/civic/variant.js @@ -185,7 +185,7 @@ const normalizeVariantRecord = ({ let rest = { type: 'fusion' }; if (tail) { - if (match = /^[a-z](\d+);[a-z](\d+)$/.exec(tail || '')) { + if (match = /^[e](\d+)-[e](\d+)$/.exec(tail || '')) { const [, exon1, exon2] = match; rest = { positional: true, variant: `fusion(e.${exon1},e.${exon2})` }; } else { diff --git a/test/civic.test.js b/test/civic.test.js index 1d5d59ba..e276bc62 100644 --- a/test/civic.test.js +++ b/test/civic.test.js @@ -258,6 +258,24 @@ describe('normalizeVariantRecord', () => { ]); }); + test('fusion with new exon notation', () => { + // EWSR1-FLI1 e7-e6 + // FLI1 Fusion + const variants = normalizeVariantRecord({ + entrezId: 1, + entrezName: 'FLI1', + name: 'EWSR1-FLI1 e7-e6', + }); + expect(variants).toEqual([ + { + positional: true, + reference1: { name: 'ewsr1' }, + reference2: { name: 'fli1', sourceId: '1' }, + variant: 'fusion(e.7,e.6)', + }, + ]); + }); + test('fusion with reference2 input gene', () => { // EML4-ALK E20;A20 // ALK FUSIONS From 53397b47d3685f3c18efe132addbfd5e40a577f3 Mon Sep 17 00:00:00 2001 From: Cam Grisdale Date: Mon, 7 Jun 2021 12:10:42 -0700 Subject: [PATCH 20/23] adding lines to load old fusion exon notation --- src/civic/variant.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/civic/variant.js b/src/civic/variant.js index 5117010e..bf8311ee 100644 --- a/src/civic/variant.js +++ b/src/civic/variant.js @@ -188,6 +188,9 @@ const normalizeVariantRecord = ({ if (match = /^[e](\d+)-[e](\d+)$/.exec(tail || '')) { const [, exon1, exon2] = match; rest = { positional: true, variant: `fusion(e.${exon1},e.${exon2})` }; + } else if (match = /^[a-z](\d+);[a-z](\d+)$/.exec(tail || '')) { + const [, exon1, exon2] = match; + rest = { positional: true, variant: `fusion(e.${exon1},e.${exon2})` }; } else { return [ ...normalizeVariantRecord({ entrezId, entrezName, name: `${gene1}-${gene2}` }), From 42e54677ce794e7b4345a53dcddf6870c2d5c431 Mon Sep 17 00:00:00 2001 From: Cam Grisdale Date: Mon, 7 Jun 2021 14:04:21 -0700 Subject: [PATCH 21/23] removing square brackets --- src/civic/variant.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/civic/variant.js b/src/civic/variant.js index bf8311ee..e92b16a5 100644 --- a/src/civic/variant.js +++ b/src/civic/variant.js @@ -185,7 +185,7 @@ const normalizeVariantRecord = ({ let rest = { type: 'fusion' }; if (tail) { - if (match = /^[e](\d+)-[e](\d+)$/.exec(tail || '')) { + if (match = /^e(\d+)-e(\d+)$/.exec(tail || '')) { const [, exon1, exon2] = match; rest = { positional: true, variant: `fusion(e.${exon1},e.${exon2})` }; } else if (match = /^[a-z](\d+);[a-z](\d+)$/.exec(tail || '')) { From 114a914ba3f90756f490dc4c6350513de412747e Mon Sep 17 00:00:00 2001 From: Cam Grisdale Date: Wed, 23 Jun 2021 13:31:04 -0700 Subject: [PATCH 22/23] update version --- package-lock.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index 75073f36..e0516605 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "@bcgsc-pori/graphkb-loader", - "version": "5.1.0", + "version": "5.1.1", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 4c7fda72..1519f315 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "@bcgsc-pori/graphkb-loader", "main": "src/index.js", - "version": "5.1.0", + "version": "5.1.1", "repository": { "type": "git", "url": "https://github.com/bcgsc/pori_graphkb_loader.git" From b7887520568af0c7349dedc973d5466cbf6b8362 Mon Sep 17 00:00:00 2001 From: Cam Grisdale Date: Mon, 5 Jul 2021 13:25:17 -0700 Subject: [PATCH 23/23] changing release version to 5.2.0 --- package-lock.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index e0516605..32e336e1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "@bcgsc-pori/graphkb-loader", - "version": "5.1.1", + "version": "5.2.0", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 1519f315..ca6c74f6 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "@bcgsc-pori/graphkb-loader", "main": "src/index.js", - "version": "5.1.1", + "version": "5.2.0", "repository": { "type": "git", "url": "https://github.com/bcgsc/pori_graphkb_loader.git"