Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat!: change strength representation #424

Draft
wants to merge 5 commits into
base: issue-240
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 11 additions & 3 deletions src/metakb/load_data.py
Original file line number Diff line number Diff line change
Expand Up @@ -479,14 +479,22 @@ def _add_statement_evidence(tx: ManagedTransaction, statement_in: dict) -> None:
if strength:
strength_key_fields = ("primaryCode", "label")

strength_keys = _create_parameterized_query(
strength, strength_key_fields, entity_param_prefix="strength_"
)
strength_keys = [
_create_parameterized_query(
strength, strength_key_fields, entity_param_prefix="strength_"
)
]
for k in strength_key_fields:
v = strength.get(k)
if v:
statement[f"strength_{k}"] = v

mappings = strength.get("mappings", [])
if mappings:
statement["strength_mappings"] = json.dumps(mappings)
strength_keys.append("mappings:$strength_mappings")

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this line is confusing me. Is this just acting as a placeholder?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This allows us to create both the strength node and statement node. Line 494 allows the transaction to access the strength values. The following lines includes the key/value pairs needed for line 499

strength_keys = ", ".join(strength_keys)

query += f"""
MERGE (strength:Strength {{ {strength_keys} }})
MERGE (s) -[:HAS_STRENGTH] -> (strength)
Expand Down
2 changes: 2 additions & 0 deletions src/metakb/query.py
Original file line number Diff line number Diff line change
Expand Up @@ -561,6 +561,8 @@ def _get_nested_stmt(
elif rel_type == "IS_REPORTED_IN":
params["reportedIn"] = [self._get_document(node)]
elif rel_type == "HAS_STRENGTH":
if "mappings" in node:
node["mappings"] = json.loads(node["mappings"])
params["strength"] = MappableConcept(**node)
elif rel_type == "HAS_THERAPEUTIC":
params["proposition"]["objectTherapeutic"] = self._get_therapy_or_group(
Expand Down
74 changes: 62 additions & 12 deletions src/metakb/transformers/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,12 @@
from ga4gh.cat_vrs.models import CategoricalVariant
from ga4gh.core import sha512t24u
from ga4gh.core.models import (
Coding,
ConceptMapping,
Extension,
MappableConcept,
Relation,
code,
)
from ga4gh.va_spec.aac_2017 import (
VariantDiagnosticStudyStatement,
Expand Down Expand Up @@ -71,22 +75,22 @@ class MethodId(str, Enum):
class CivicEvidenceLevel(str, Enum):
"""Define constraints for CIViC evidence levels"""

A = "civic.evidence_level:A"
B = "civic.evidence_level:B"
C = "civic.evidence_level:C"
D = "civic.evidence_level:D"
E = "civic.evidence_level:E"
A = "A"
B = "B"
C = "C"
D = "D"
E = "E"


class MoaEvidenceLevel(str, Enum):
"""Define constraints MOAlmanac evidence levels"""

FDA_APPROVED = "moa.evidence_level:fda_approved"
GUIDELINE = "moa.evidence_level:guideline"
CLINICAL_TRIAL = "moa.evidence_level:clinical_trial"
CLINICAL_EVIDENCE = "moa.evidence_level:clinical_evidence"
PRECLINICAL = "moa.evidence_level:preclinical_evidence"
INFERENTIAL = "moa.evidence_level:inferential_evidence"
FDA_APPROVED = "FDA-Approved"
GUIDELINE = "Guideline"
CLINICAL_TRIAL = "Clinical trial"
CLINICAL_EVIDENCE = "Clinical evidence"
PRECLINICAL = "Preclinical evidence"
INFERENTIAL = "Inferential evidence"


class TherapyType(str, Enum):
Expand Down Expand Up @@ -323,12 +327,58 @@ def _evidence_level_to_vicc_concept_mapping(
to corresponding vicc concept vocab (value) represented as MappableConcept
object
"""

def _get_concept_mapping(exact_mapping: str) -> ConceptMapping:
"""Get system for an exact mapping

:param exact_mapping: Exact mapping code
:raises NotImplementedError: If SourceName not supported yet
:return: Concept mapping object
"""
if isinstance(exact_mapping, EcoLevel):
id_ = exact_mapping.value.lower()
system = "https://www.evidenceontology.org/term/"
elif isinstance(exact_mapping, CivicEvidenceLevel):
system = (
"https://civic.readthedocs.io/en/latest/model/evidence/level.html"
)
id_ = f"{SourceName.CIVIC.value}.evidence_level:{exact_mapping.value}"
elif isinstance(exact_mapping, MoaEvidenceLevel):
system = "https://moalmanac.org/about"
id_ = f"{SourceName.MOA.value}.assertion_level:{'_'.join(exact_mapping.value.lower().replace('-', '_').split())}"
else:
raise NotImplementedError

return ConceptMapping(
coding=Coding(id=id_, system=system, code=exact_mapping),
relation=Relation.EXACT_MATCH,
)

mappings = {}
for item in self._vicc_concept_vocabs:
primary_code = item.id.split(":")[-1]
for exact_mapping in item.exact_mappings:
concept_mappings = [
ConceptMapping(
coding=Coding(
id=item.id,
system="https://go.osu.edu/evidence-codes",
label=item.term,
code=code(primary_code),
),
relation=Relation.EXACT_MATCH,
)
]

concept_mappings.extend(
_get_concept_mapping(exact_mapping_)
for exact_mapping_ in item.exact_mappings
)

mappings[exact_mapping] = MappableConcept(
label=item.term,
primaryCode=item.id.split(":")[-1],
primaryCode=primary_code,
mappings=concept_mappings,
)

return mappings
Expand Down
103 changes: 103 additions & 0 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -361,6 +361,25 @@ def civic_eid2997_study_stmt(
"strength": {
"primaryCode": "e000001",
"label": "authoritative evidence",
"mappings": [
{
"coding": {
"id": "vicc:e000001",
"system": "https://go.osu.edu/evidence-codes",
"label": "authoritative evidence",
"code": "e000001",
},
"relation": "exactMatch",
},
{
"coding": {
"id": "civic.evidence_level:A",
"system": "https://civic.readthedocs.io/en/latest/model/evidence/level.html",
"code": "A",
},
"relation": "exactMatch",
},
],
},
"proposition": {
"type": "VariantTherapeuticResponseProposition",
Expand Down Expand Up @@ -969,6 +988,25 @@ def civic_eid816_study_stmt(
"strength": {
"primaryCode": "e000005",
"label": "clinical cohort evidence",
"mappings": [
{
"coding": {
"id": "vicc:e000005",
"system": "https://go.osu.edu/evidence-codes",
"code": "e000005",
"label": "clinical cohort evidence",
},
"relation": "exactMatch",
},
{
"coding": {
"id": "civic.evidence_level:B",
"system": "https://civic.readthedocs.io/en/latest/model/evidence/level.html",
"code": "B",
},
"relation": "exactMatch",
},
],
},
"proposition": {
"type": "VariantTherapeuticResponseProposition",
Expand Down Expand Up @@ -1009,6 +1047,25 @@ def civic_eid9851_study_stmt(
"strength": {
"primaryCode": "e000001",
"label": "authoritative evidence",
"mappings": [
{
"coding": {
"id": "vicc:e000001",
"system": "https://go.osu.edu/evidence-codes",
"code": "e000001",
"label": "authoritative evidence",
},
"relation": "exactMatch",
},
{
"coding": {
"id": "civic.evidence_level:A",
"system": "https://civic.readthedocs.io/en/latest/model/evidence/level.html",
"code": "A",
},
"relation": "exactMatch",
},
],
},
"proposition": {
"type": "VariantTherapeuticResponseProposition",
Expand Down Expand Up @@ -1114,6 +1171,25 @@ def civic_eid26_study_stmt(
"strength": {
"primaryCode": "e000005",
"label": "clinical cohort evidence",
"mappings": [
{
"coding": {
"id": "vicc:e000005",
"system": "https://go.osu.edu/evidence-codes",
"code": "e000005",
"label": "clinical cohort evidence",
},
"relation": "exactMatch",
},
{
"coding": {
"id": "civic.evidence_level:B",
"system": "https://civic.readthedocs.io/en/latest/model/evidence/level.html",
"code": "B",
},
"relation": "exactMatch",
},
],
},
"proposition": {
"type": "VariantPrognosticProposition",
Expand Down Expand Up @@ -1423,6 +1499,33 @@ def moa_aid66_study_stmt(
"strength": {
"primaryCode": "e000009",
"label": "preclinical evidence",
"mappings": [
{
"coding": {
"id": "vicc:e000009",
"system": "https://go.osu.edu/evidence-codes",
"code": "e000009",
"label": "preclinical evidence",
},
"relation": "exactMatch",
},
{
"coding": {
"id": "civic.evidence_level:D",
"system": "https://civic.readthedocs.io/en/latest/model/evidence/level.html",
"code": "D",
},
"relation": "exactMatch",
},
{
"coding": {
"id": "moa.assertion_level:preclinical_evidence",
"system": "https://moalmanac.org/about",
"code": "Preclinical evidence",
},
"relation": "exactMatch",
},
],
},
"direction": "supports",
"proposition": {
Expand Down
51 changes: 50 additions & 1 deletion tests/unit/database/test_database.py
Original file line number Diff line number Diff line change
Expand Up @@ -548,7 +548,7 @@ def test_statement_rules(
check_relation_count("Statement", "CategoricalVariant", "HAS_VARIANT")
check_relation_count("Statement", "Condition", "HAS_TUMOR_TYPE")
check_relation_count("Statement", "Therapy", "HAS_THERAPEUTIC", min_rels=0)
check_relation_count("Statement", "MappableConcept", "HAS_STRENGTH", min_rels=0)
check_relation_count("Statement", "Strength", "HAS_STRENGTH", min_rels=0)
check_relation_count("Statement", "Method", "IS_SPECIFIED_BY", max_rels=None)
check_relation_count("Statement", "Gene", "HAS_GENE_CONTEXT", max_rels=None)
check_relation_count(
Expand Down Expand Up @@ -634,6 +634,55 @@ def test_statement_rules(
check_node_props(statement, civic_aid6_ss_cp, expected_keys)


def test_strength_rules(driver: Driver, check_relation_count, civic_eid2997_study_stmt):
"""Verify property and relationship rules for Strength nodes."""
query = """
MATCH (s:Strength)
WITH s.label AS label, s.primaryCode AS primaryCode, COUNT(*) AS count
WHERE count > 1
RETURN COUNT(*)
"""
with driver.session() as s:
record = s.run(query).single()
assert record.values()[0] == 0

# Evidence items should have strength
cite_query = """
MATCH (s:Statement)
OPTIONAL MATCH (s)-[:HAS_STRENGTH]->(st:Strength)
WITH s, COUNT(st) as strength_count
WHERE strength_count < 1 AND NOT s.id STARTS WITH 'civic.aid:'
RETURN COUNT(s)
"""
with driver.session() as s:
record = s.run(cite_query).single()
assert record.values()[0] == 0

# Assertions do not have strength
cite_query = """
MATCH (s:Statement)
OPTIONAL MATCH (s)-[:HAS_STRENGTH]->(st:Strength)
WITH s, COUNT(st) as strength_count
WHERE strength_count > 1 AND s.id STARTS WITH 'civic.aid:'
RETURN COUNT(s)
"""
with driver.session() as s:
record = s.run(cite_query).single()
assert record.values()[0] == 0

query = f"""
MATCH (s:Strength {{primaryCode: '{civic_eid2997_study_stmt['strength']['primaryCode']}', label: '{civic_eid2997_study_stmt['strength']['label']}'}})
RETURN s
"""
result = driver.execute_query(query)
assert len(result.records) == 1
strength_node = result.records[0].data()["s"]

assert strength_node.keys() == civic_eid2997_study_stmt["strength"].keys()
strength_node["mappings"] = json.loads(strength_node["mappings"])
assert strength_node == civic_eid2997_study_stmt["strength"]


def test_classification_rules(
driver: Driver, check_unique_property, check_relation_count, civic_aid6_statement
):
Expand Down
38 changes: 38 additions & 0 deletions tests/unit/transformers/test_civic_transformer_diagnostic.py
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,25 @@ def civic_eid2_study_stmt(civic_method, civic_mpid99, civic_gid38, civic_did2):
"strength": {
"primaryCode": "e000005",
"label": "clinical cohort evidence",
"mappings": [
{
"coding": {
"id": "vicc:e000005",
"system": "https://go.osu.edu/evidence-codes",
"code": "e000005",
"label": "clinical cohort evidence",
},
"relation": "exactMatch",
},
{
"coding": {
"id": "civic.evidence_level:B",
"system": "https://civic.readthedocs.io/en/latest/model/evidence/level.html",
"code": "B",
},
"relation": "exactMatch",
},
],
},
"proposition": {
"type": "VariantDiagnosticProposition",
Expand Down Expand Up @@ -498,6 +517,25 @@ def civic_eid74_study_stmt(civic_method, civic_mpid113, civic_gid42, civic_did15
"strength": {
"primaryCode": "e000005",
"label": "clinical cohort evidence",
"mappings": [
{
"coding": {
"id": "vicc:e000005",
"system": "https://go.osu.edu/evidence-codes",
"code": "e000005",
"label": "clinical cohort evidence",
},
"relation": "exactMatch",
},
{
"coding": {
"id": "civic.evidence_level:B",
"system": "https://civic.readthedocs.io/en/latest/model/evidence/level.html",
"code": "B",
},
"relation": "exactMatch",
},
],
},
"proposition": {
"type": "VariantDiagnosticProposition",
Expand Down
Loading
Loading