Skip to content

Explore GKM Toolkit features with CIViC bundle examples

Data files

Example files: civic-assertion-251-bundle.json · civic-assertion-9-bundle.json · civic-gkm-bundle-v0.1.0-a0.schema.json

Rendered from notebooks/civic/bundles/explore-civic-bundles.ipynb.

Use this walkthrough to learn how the GKM Toolkit works with CIViC bundle data.

Start with a small, focused CIViC bundle example. Then inspect its schema and collections, follow an assertion's links, and prepare its data for another tool.

  1. Load the CIViC bundle.
  2. Understand its schema and collections.
  3. Find and resolve an assertion.
  4. Normalize, denormalize, and export the result.

This walkthrough uses two small, focused subsets of CIViC's actual published dataset. They keep the examples focused while highlighting the Toolkit operations used to explore a bundle.

Set up

How do we work with a bundle in Python?

Import the bundles package. It provides the loader, in-memory bundle model, reference lookup, and export operations used below.

In [1]
import json
from pathlib import Path
from typing import Any

from ga4gh.gkm import bundles

Locate the bundle schema and bundles

A bundle schema defines the constraints for a producer-defined bundle and identifies the GKM schema versions it uses.

A bundle is the JSON data that follows those constraints, containing related GKM objects grouped into named collections.

We will use two CIViC bundle examples and their shared schema stored with this repository. Each contains actual CIViC records selected for this walkthrough.

In [2]
bundle_dir = Path()
civic_assertion_9_bundle_name = "civic-assertion-9"
civic_assertion_251_bundle_name = "civic-assertion-251"
civic_assertion_9_path = bundle_dir / f"{civic_assertion_9_bundle_name}-bundle.json"
civic_assertion_251_path = bundle_dir / f"{civic_assertion_251_bundle_name}-bundle.json"
schema_path = bundle_dir / "civic-gkm-bundle-v0.1.0-a0.schema.json"
print("Example directory:", bundle_dir)
print(
    "Bundle files:", civic_assertion_9_path.name, "and", civic_assertion_251_path.name
)
print("Schema file:", schema_path.name)

Output:

Example directory: .
Bundle files: civic-assertion-9-bundle.json and civic-assertion-251-bundle.json
Schema file: civic-gkm-bundle-v0.1.0-a0.schema.json

Can the installed libraries interpret this bundle?

The bundle schema identifies the GKM product versions used by its collections. supported_gkm_versions() simply lists the versions supported by the installed GKM Toolkit; it does not check a bundle.

In [3]
with schema_path.open(encoding="utf-8") as stream:
    civic_schema = json.load(stream)

bundles.supported_gkm_versions()

Output:

{'gkm-core': '1.3.0', 'vrs': '2.1.1', 'cat-vrs': '1.1.1', 'va-spec': '1.1.0'}

Now check whether this bundle can be used by the installed GKM Toolkit. check_gkm_version_compatibility compares the versions in the bundle schema with the supported versions and raises an error when they are not compatible.

This checks GKM versions; it does not perform full JSON Schema validation.

In [4]
bundles.check_gkm_version_compatibility(civic_schema)

What does the bundle schema tell us?

The schema contains the producer's bundle structure and other constraints. This walkthrough highlights its title, description, and collection definitions; read the schema directly for the complete specification.

In [5]
print("Title:", civic_schema.get("title", "(no title)"))
print("Description:", civic_schema.get("description", "(no description)"))

Output:

Title: CIViC GKM Bundle v0.1.0-a0
Description: CIViC organizes curated cancer variant knowledge around variants and molecular profiles with evidence from source publications, summary assertions, and clinical context such as diseases, therapies, phenotypes, variant origins, and curating organizations. This schema describes a GA4GH GKM representation of those CIViC concepts. Top-level keys use CIViC knowledge model terms where possible, with additional keys for supporting GKM representation details. For the CIViC data model, see https://civic.readthedocs.io/en/latest/model.html.

Load and inspect

How do we load the bundle for repeated use?

The registry is optional: you can load a bundle directly from its source. Here, registration associates a short name with each bundle file, its schema, and producer information so we can load the examples by name. Registration is local; it does not download or publish a bundle.

replace=True makes registration safe to rerun.

In [6]
for name, source in {
    civic_assertion_9_bundle_name: civic_assertion_9_path,
    civic_assertion_251_bundle_name: civic_assertion_251_path,
}.items():
    bundles.registry.register(
        bundles.BundleRegistration(
            name=name,
            source=source,
            schema=schema_path,
            producer="CIViC",
        ),
        replace=True,
    )

How do we load the registered examples?

Now load both bundles by name. load_bundles() uses each registered schema to check GKM version compatibility as part of loading. The earlier compatibility check demonstrated this validation explicitly; it was not required before calling load_bundles().

In [7]
loaded_bundles = bundles.load_bundles(
    civic_assertion_9_bundle_name, civic_assertion_251_bundle_name
)
loaded_bundles

Output:

{'civic-assertion-9': Bundle(name='civic-assertion-9', collections=17),
 'civic-assertion-251': Bundle(name='civic-assertion-251', collections=17)}

Which loaded bundle will we explore?

We will use Assertion 9 for the reference and export walkthrough, then compare it with Assertion 251 later.

In [8]
civic_assertion_9_bundle = loaded_bundles[civic_assertion_9_bundle_name]
civic_assertion_251_bundle = loaded_bundles[civic_assertion_251_bundle_name]
civic_assertion_9_bundle, civic_assertion_251_bundle

Output:

(Bundle(name='civic-assertion-9', collections=17),
 Bundle(name='civic-assertion-251', collections=17))

What does the producer put in the bundle?

The GKM Toolkit preserves the producer's collection names. Use collection_names() to see what the loaded bundle contains, then inspect a collection and its identifiers before working with individual objects.

In [9]
civic_assertion_9_bundle.collection_names()

Output:

('sequenceReference',
 'location',
 'variant',
 'feature',
 'molecularProfile',
 'disease',
 'phenotype',
 'conditionSet',
 'therapy',
 'therapyGroup',
 'variantOrigin',
 'source',
 'method',
 'organization',
 'proposition',
 'evidence',
 'assertion')

Access a collection

Each named collection is represented by a BundleCollection, which maps the producer's object identifiers to objects. Collections support attribute access, mapping syntax, and the explicit collection() method.

In [10]
sequence_reference_collection = civic_assertion_9_bundle.sequenceReference

assert isinstance(sequence_reference_collection, bundles.BundleCollection)
assert sequence_reference_collection is civic_assertion_9_bundle["sequenceReference"]
assert sequence_reference_collection is civic_assertion_9_bundle.collection(
    "sequenceReference"
)

sequence_reference_collection

Output:

BundleCollection(name='sequenceReference', size=3)

What if a collection name is not present?

Collection names are producer-defined. This example shows the kind of error that can occur when a name is entered incorrectly (an extra 's' added). Use collection_names() to discover valid names before accessing a collection.

In [11]
try:
    civic_assertion_9_bundle.sequenceReferences  # noqa: B018
except bundles.BundleCollectionNotFoundError as error:
    print(error)

Output:

Unknown collection 'sequenceReferences'

List object identifiers

Use keys() to see which object identifiers are available in the collection.

In [12]
sequence_reference_collection_keys = list(sequence_reference_collection.keys())
sequence_reference_collection_keys

Output:

['SQ.6CnHhDq_bDCsuIBf0AzxtKq_lXYM7f0m',
 'SQ.EJQv9rQmiD76iFmXsLwCy2dJHOFO3bpj',
 'SQ.pnAqCRBrTsUoBghSD1yp_jXWSmlbdh4g']

Work with GKM objects

What do we get back for a supported object?

When an object is supported by an installed GKM reference library, the GKM Toolkit loads it as that library's Python model instead of leaving it as a raw dictionary. The example below retrieves a VRS SequenceReference by its identifier.

In [13]
sequence_id = sequence_reference_collection_keys[0]
sequence_reference = sequence_reference_collection[sequence_id]
sequence_reference

Output:

SequenceReference(id=None, type='SequenceReference', name=None, description=None, aliases=None, extensions=None, refgetAccession='SQ.6CnHhDq_bDCsuIBf0AzxtKq_lXYM7f0m', residueAlphabet=None, circular=None, sequence=None, moleculeType=None)

Why is this a SequenceReference?

The schema entry for the collection tells us how its contents are described. First inspect its keys. Then we can see why dynamic collection identifiers use patternProperties.

In [14]
sequence_reference_schema = civic_schema["properties"]["sequenceReference"]
print("Schema entry keys:", list(sequence_reference_schema))
sequence_reference_pattern, sequence_reference_definition = next(
    iter(sequence_reference_schema["patternProperties"].items())
)
schema_ref = sequence_reference_definition["$ref"]
print("Key pattern:", sequence_reference_pattern)
print("Schema reference:", schema_ref)
print("Loaded object type:", sequence_reference.type)

Output:

Schema entry keys: ['additionalProperties', 'description', 'patternProperties', 'title', 'type']
Key pattern: ^SQ\.[A-Za-z0-9_-]+$
Schema reference: https://w3id.org/ga4gh/schema/vrs/2.1.1/json/SequenceReference
Loaded object type: SequenceReference

What if an object identifier is not present?

This example shows the kind of error that can occur when an identifier is entered incorrectly. Identifiers come from the bundle data, so use the collection's keys to find a valid one.

In [15]
missing_sequence_id = sequence_id[:-1] + "x"

try:
    sequence_reference_collection[missing_sequence_id]
except bundles.BundleObjectNotFoundError as error:
    print(error)

Output:

"Unknown identifier 'SQ.6CnHhDq_bDCsuIBf0AzxtKq_lXYM7f0x' in collection 'sequenceReference'"

Which proposition does this assertion refer to?

Collection entries are typed GKM models, and linked fields may already be resolved. Get a bundle-local JSON Pointer from the JSON-compatible output of to_dict(). Here, the assertion's proposition field is a pointer to its proposition in the same bundle.

In [16]
assertion_9_id = "civic.aid:9"
assertion_9 = civic_assertion_9_bundle.assertion[assertion_9_id]
bundle_document = civic_assertion_9_bundle.to_dict()
assertion_9_pointer = bundle_document["assertion"][assertion_9_id]["proposition"]
assertion_9_pointer

Output:

'#/proposition/civic.proposition:fOBF0e3ZunhJ23AdC3O3m2Vg5k_ARxkv'

Pass resolve() a bundle-local JSON Pointer, such as one from to_dict(). It follows the pointer and returns the referenced object as a typed GKM model.

In [17]
proposition_pointer = assertion_9_pointer
proposition_9 = civic_assertion_9_bundle.resolve(proposition_pointer)
print("Pointer:", proposition_pointer)
print("Resolved type:", proposition_9.type)

Output:

Pointer: #/proposition/civic.proposition:fOBF0e3ZunhJ23AdC3O3m2Vg5k_ARxkv
Resolved type: VariantClinicalSignificanceProposition

The resolved object is a typed GKM proposition, and its fields may already contain resolved GKM objects. Use to_dict() to inspect the JSON-compatible bundle representation with local references preserved.

In [18]
compact_proposition = bundle_document["proposition"][proposition_9.id]
print(json.dumps(compact_proposition, indent=2))

Output:

{
  "id": "civic.proposition:fOBF0e3ZunhJ23AdC3O3m2Vg5k_ARxkv",
  "type": "VariantClinicalSignificanceProposition",
  "subject": "#/molecularProfile/civic.mpid:1594",
  "predicate": "hasClinicalSignificanceFor",
  "object": "#/disease/civic.did:2950",
  "geneContextQualifier": "#/feature/civic.gid:154",
  "alleleOriginQualifier": "#/variantOrigin/civic.variantOrigin:SOMATIC"
}

normalize() replaces every reachable local pointer with inline data, producing a self-contained JSON-compatible view. Here it starts from the compact proposition so the expansion is explicit. The complete result can be large, so this example displays only a few fields from the expanded variant and condition.

In [19]
inline_proposition_9 = civic_assertion_9_bundle.normalize(compact_proposition)
inline_preview = {
    "type": inline_proposition_9["type"],
    "subject": {
        "id": inline_proposition_9["subject"]["id"],
        "name": inline_proposition_9["subject"]["name"],
    },
    "object": {
        "id": inline_proposition_9["object"]["id"],
        "name": inline_proposition_9["object"]["name"],
    },
    "alleleOriginQualifier": inline_proposition_9["alleleOriginQualifier"],
}
print(json.dumps(inline_preview, indent=2))

Output:

{
  "type": "VariantClinicalSignificanceProposition",
  "subject": {
    "id": "civic.mpid:1594",
    "name": "ACVR1 G328V"
  },
  "object": {
    "id": "civic.did:2950",
    "name": "Diffuse Midline Glioma, H3 K27-altered"
  },
  "alleleOriginQualifier": {
    "id": "civic.variantOrigin:SOMATIC",
    "type": "MappableConcept",
    "name": "somatic",
    "mappings": [
      {
        "coding": {
          "system": "https://civicdb.org",
          "code": "SOMATIC",
          "iris": [
            "https://civic.readthedocs.io/en/latest/model/evidence/origin.html"
          ]
        },
        "relation": "exactMatch"
      }
    ]
  }
}

Compare assertions

The two bundles have the same CIViC-defined organization, but their assertions answer different scientific questions. A small helper can apply the same workflow to both and compare selected fields.

In [20]
def assertion_summary(bundle: bundles.Bundle, assertion_id: str) -> dict[str, str]:
    """Summarize one assertion and its referenced proposition.

    :param bundle: Bundle containing the assertion.
    :param assertion_id: Collection key for the assertion.
    :return: Selected assertion, classification, and proposition fields.
    """
    assertion = bundle.assertion[assertion_id]
    proposition_pointer = bundle.to_dict()["assertion"][assertion_id]["proposition"]
    proposition = bundle.resolve(proposition_pointer)
    coding = assertion.classification.primaryCoding
    return {
        "assertion": assertion_id,
        "classification_system": str(coding.system),
        "classification": str(coding.code.root),
        "proposition_type": str(proposition.type),
        "predicate": str(proposition.predicate),
    }


summaries = [
    assertion_summary(civic_assertion_9_bundle, assertion_9_id),
    assertion_summary(civic_assertion_251_bundle, "civic.aid:251"),
]
print(json.dumps(summaries, indent=2))

Output:

[
  {
    "assertion": "civic.aid:9",
    "classification_system": "AMP/ASCO/CAP Guidelines, 2017",
    "classification": "tier ii",
    "proposition_type": "VariantClinicalSignificanceProposition",
    "predicate": "hasClinicalSignificanceFor"
  },
  {
    "assertion": "civic.aid:251",
    "classification_system": "ClinGen/CGC/VICC Guidelines for Oncogenicity, 2022",
    "classification": "likely oncogenic",
    "proposition_type": "VariantOncogenicityProposition",
    "predicate": "isOncogenicFor"
  }
]

How do we prepare data for another tool?

Suppose a review tool needs one assertion and its linked variant and condition, rather than the complete CIViC bundle. to_dict() provides JSON-compatible bundle values, which you can select and combine with the dereferenced proposition to create that smaller payload.

The resulting review_payload is application-specific data, not a CIViC bundle. This walkthrough keeps it in memory; an application could serialize it as JSON when needed.

Use Bundle.to_dict() for the complete bundle and model_dump() for an individual GKM Python model.

In [21]
bundle_data = civic_assertion_9_bundle.to_dict()
review_payload = {
    "assertion": bundle_data["assertion"][assertion_9_id],
    "proposition": inline_proposition_9,
}

review_summary = {
    "assertionId": review_payload["assertion"]["id"],
    "classification": review_payload["assertion"]["classification"]["name"],
    "variant": review_payload["proposition"]["subject"]["name"],
    "condition": review_payload["proposition"]["object"]["name"],
}
print(json.dumps(review_summary, indent=2))

Output:

{
  "assertionId": "civic.aid:9",
  "classification": "Tier II",
  "variant": "ACVR1 G328V",
  "condition": "Diffuse Midline Glioma, H3 K27-altered"
}

Return an assertion to bundle form

Normalize the assertion so its referenced content is available inline. Then restore its local references and export it in the form another tool needs.

How do we restore the bundle references?

denormalize() replaces expanded content with the local pointers known by the bundle. This returns the assertion to its compact bundle representation.

In [22]
normalized_assertion = civic_assertion_9_bundle.normalize(assertion_9)
denormalized_assertion = civic_assertion_9_bundle.denormalize(normalized_assertion)


def local_pointers(value: Any) -> list[str]:  # noqa: ANN401
    """Return local JSON Pointer strings found in a nested value.

    :param value: Value to inspect recursively.
    :returns: Local JSON Pointer strings.
    """
    if isinstance(value, str) and value.startswith("#/"):
        return [value]
    if isinstance(value, dict):
        return [pointer for item in value.values() for pointer in local_pointers(item)]
    if isinstance(value, list):
        return [pointer for item in value for pointer in local_pointers(item)]
    return []


print("Local pointers in denormalized assertion:")
print(json.dumps(local_pointers(denormalized_assertion), indent=2))

Output:

Local pointers in denormalized assertion:
[
  "#/method/civic.method:2019",
  "#/proposition/civic.proposition:fOBF0e3ZunhJ23AdC3O3m2Vg5k_ARxkv",
  "#/proposition/civic.proposition:H6qvcvpF_jzQmVg72PCxDbwJIAsMh58Q",
  "#/evidence/civic.eid:4846",
  "#/evidence/civic.eid:6955"
]

How do we export the result?

Use export(deep=False) to keep local pointers, or export(deep=True) when the receiving tool needs the referenced content inline.

In [23]
shallow_assertion = civic_assertion_9_bundle.export(denormalized_assertion, deep=False)
print("deep=False proposition:", shallow_assertion["proposition"])

Output:

deep=False proposition: #/proposition/civic.proposition:fOBF0e3ZunhJ23AdC3O3m2Vg5k_ARxkv

The shallow export preserves the pointer form for a compact bundle-compatible object. The deep export includes the referenced proposition for a standalone payload.

In [24]
deep_assertion = civic_assertion_9_bundle.export(denormalized_assertion, deep=True)
print("deep=True proposition:", deep_assertion["proposition"])

Output:

deep=True proposition: {'id': 'civic.proposition:fOBF0e3ZunhJ23AdC3O3m2Vg5k_ARxkv', 'type': 'VariantClinicalSignificanceProposition', 'subject': {'id': 'civic.mpid:1594', 'type': 'CategoricalVariant', 'name': 'ACVR1 G328V', 'aliases': ['GLY328VAL'], 'extensions': [{'name': 'molecularProfileScore', 'value': 35.0}, {'name': 'hgvsDescriptions', 'value': ['NM_001105.4:c.983G>T', 'NP_001096.1:p.Gly328Val', 'NC_000002.11:g.158622516C>A', 'ENST00000434821.1:c.983G>T', 'NC_000002.12:g.157766004C>A', 'NM_001111067.4:c.983G>T', 'NP_001104537.1:p.Gly328Val', 'ENST00000434821.7:c.983G>T', 'ENSP00000405004.1:p.Gly328Val']}, {'name': 'maneSelectTranscript', 'value': 'ENST00000434821.7:c.983G>T'}, {'name': 'representativeVariantCoordinates', 'value': {'chromosome': '2', 'start': 158622516, 'stop': 158622516, 'reference_bases': 'C', 'variant_bases': 'A', 'ensembl_version': 75, 'representative_transcript': 'ENST00000434821.1', 'reference_build': 'GRCh37', 'type': 'coordinates'}}, {'name': 'categoricalVariationType', 'value': 'ProteinSequenceConsequence'}], 'members': [{'id': 'ga4gh:VA.knLN28eRu0f2IUAQBHwXjvjyKyNNwb9N', 'type': 'Allele', 'name': 'NM_001111067.4:c.983G>T', 'digest': 'knLN28eRu0f2IUAQBHwXjvjyKyNNwb9N', 'expressions': [{'syntax': 'hgvs.c', 'value': 'NM_001105.4:c.983G>T'}, {'syntax': 'hgvs.c', 'value': 'NM_001111067.4:c.983G>T'}], 'location': {'id': 'ga4gh:SL.DO4BZ8csWCDedM5lh7NrmIpS3RnboBHw', 'type': 'SequenceLocation', 'digest': 'DO4BZ8csWCDedM5lh7NrmIpS3RnboBHw', 'sequenceReference': {'type': 'SequenceReference', 'refgetAccession': 'SQ.EJQv9rQmiD76iFmXsLwCy2dJHOFO3bpj'}, 'start': 1699, 'end': 1700, 'sequence': 'G'}, 'state': {'type': 'LiteralSequenceExpression', 'sequence': 'T'}}, {'id': 'ga4gh:VA.affc26OivYhQEhNjs0NS2f3-2BYoEsey', 'type': 'Allele', 'name': 'NC_000002.12:g.157766004C>A', 'digest': 'affc26OivYhQEhNjs0NS2f3-2BYoEsey', 'expressions': [{'syntax': 'hgvs.g', 'value': 'NC_000002.11:g.158622516C>A'}, {'syntax': 'hgvs.g', 'value': 'NC_000002.12:g.157766004C>A'}], 'location': {'id': 'ga4gh:SL.ET6dAkJ468aUfP3iLEWuG_Yfl_gFMDq0', 'type': 'SequenceLocation', 'digest': 'ET6dAkJ468aUfP3iLEWuG_Yfl_gFMDq0', 'sequenceReference': {'type': 'SequenceReference', 'refgetAccession': 'SQ.pnAqCRBrTsUoBghSD1yp_jXWSmlbdh4g'}, 'start': 157766003, 'end': 157766004, 'sequence': 'C'}, 'state': {'type': 'LiteralSequenceExpression', 'sequence': 'A'}}, {'id': 'ga4gh:VA.fcWuwB4g25bTPp52iyTF7DnBNPm5POer', 'type': 'Allele', 'name': 'ACVR1 G328V', 'digest': 'fcWuwB4g25bTPp52iyTF7DnBNPm5POer', 'expressions': [{'syntax': 'hgvs.p', 'value': 'NP_001096.1:p.Gly328Val'}, {'syntax': 'hgvs.p', 'value': 'NP_001104537.1:p.Gly328Val'}, {'syntax': 'hgvs.p', 'value': 'ENSP00000405004.1:p.Gly328Val'}], 'location': {'id': 'ga4gh:SL.cOMztEW7PBkzDSr_gkVyzfYDcmH8fp3G', 'type': 'SequenceLocation', 'digest': 'cOMztEW7PBkzDSr_gkVyzfYDcmH8fp3G', 'sequenceReference': {'type': 'SequenceReference', 'refgetAccession': 'SQ.6CnHhDq_bDCsuIBf0AzxtKq_lXYM7f0m'}, 'start': 327, 'end': 328, 'sequence': 'G'}, 'state': {'type': 'LiteralSequenceExpression', 'sequence': 'V'}}], 'constraints': [{'type': 'DefiningAlleleConstraint', 'allele': {'id': 'ga4gh:VA.fcWuwB4g25bTPp52iyTF7DnBNPm5POer', 'type': 'Allele', 'name': 'ACVR1 G328V', 'digest': 'fcWuwB4g25bTPp52iyTF7DnBNPm5POer', 'expressions': [{'syntax': 'hgvs.p', 'value': 'NP_001096.1:p.Gly328Val'}, {'syntax': 'hgvs.p', 'value': 'NP_001104537.1:p.Gly328Val'}, {'syntax': 'hgvs.p', 'value': 'ENSP00000405004.1:p.Gly328Val'}], 'location': {'id': 'ga4gh:SL.cOMztEW7PBkzDSr_gkVyzfYDcmH8fp3G', 'type': 'SequenceLocation', 'digest': 'cOMztEW7PBkzDSr_gkVyzfYDcmH8fp3G', 'sequenceReference': {'type': 'SequenceReference', 'refgetAccession': 'SQ.6CnHhDq_bDCsuIBf0AzxtKq_lXYM7f0m'}, 'start': 327, 'end': 328, 'sequence': 'G'}, 'state': {'type': 'LiteralSequenceExpression', 'sequence': 'V'}}, 'relations': [{'type': 'MappableConcept', 'primaryCoding': {'system': 'ga4gh-gkm-term:allele-relation', 'code': 'liftover_to'}}, {'type': 'MappableConcept', 'primaryCoding': {'system': 'http://www.sequenceontology.org', 'code': 'translation_of'}}]}], 'mappings': [{'coding': {'id': 'civic.mpid:1594', 'system': 'https://civicdb.org/links/molecular_profile/', 'code': '1594'}, 'relation': 'exactMatch'}, {'coding': {'id': 'civic.vid:1686', 'extensions': [{'name': 'subtype', 'value': 'gene_variant'}, {'name': 'variantTypes', 'value': [{'coding': {'id': 'civic.variant_type:47', 'name': 'Missense Variant', 'system': 'http://www.sequenceontology.org/browser/current_svn/term/', 'code': 'SO:0001583'}, 'relation': 'exactMatch'}]}], 'name': 'G328V', 'system': 'https://civicdb.org/links/variant/', 'code': '1686'}, 'relation': 'exactMatch'}, {'coding': {'id': 'clingen.allele:CA16602802', 'system': 'https://reg.clinicalgenome.org/redmine/projects/registry/genboree_registry/by_canonicalid?canonicalid=', 'code': 'CA16602802'}, 'relation': 'relatedMatch'}, {'coding': {'id': 'clinvar:376363', 'system': 'https://www.ncbi.nlm.nih.gov/clinvar/variation/', 'code': '376363'}, 'relation': 'relatedMatch'}, {'coding': {'id': 'dbsnp:rs387906589', 'system': 'https://www.ncbi.nlm.nih.gov/snp/', 'code': 'rs387906589'}, 'relation': 'relatedMatch'}]}, 'predicate': 'hasClinicalSignificanceFor', 'object': {'id': 'civic.did:2950', 'type': 'MappableConcept', 'name': 'Diffuse Midline Glioma, H3 K27-altered', 'conceptType': 'Disease', 'mappings': [{'coding': {'system': 'https://disease-ontology.org/?id=', 'code': 'DOID:0080684'}, 'relation': 'exactMatch'}]}, 'geneContextQualifier': {'id': 'civic.gid:154', 'type': 'MappableConcept', 'name': 'ACVR1', 'extensions': [{'name': 'aliases', 'value': ['ACTRI', 'ACVR1', 'ACVR1A', 'ACVRLK2', 'ALK2', 'FOP', 'SKR1', 'TSRI']}], 'conceptType': 'Gene', 'mappings': [{'coding': {'id': 'ncbigene:90', 'system': 'https://www.ncbi.nlm.nih.gov/gene/', 'code': '90'}, 'relation': 'exactMatch'}]}, 'alleleOriginQualifier': {'id': 'civic.variantOrigin:SOMATIC', 'type': 'MappableConcept', 'name': 'somatic', 'mappings': [{'coding': {'system': 'https://civicdb.org', 'code': 'SOMATIC', 'iris': ['https://civic.readthedocs.io/en/latest/model/evidence/origin.html']}, 'relation': 'exactMatch'}]}}