From 50752033f87b711b7b8657c96fc14e4b1aac0657 Mon Sep 17 00:00:00 2001
From: Kori Kuzma <korikuzma@gmail.com>
Date: Thu, 16 Jan 2025 11:57:31 -0500
Subject: [PATCH] fix!: use correct representation of `Coding` object in
 `mappings`

* `system` MUST use `iriReference`, not a free-text label
* `code` MUST use syntax defined by the `system`
* `id` will use record `concept_id`
---
 .github/workflows/checks.yaml                 |   2 +-
 .../source/normalizing_data/normalization.rst |  48 ++-
 src/gene/query.py                             |  18 +-
 src/gene/schemas.py                           | 118 ++++----
 tests/unit/test_query.py                      | 275 +++++++++++-------
 tests/unit/test_schemas.py                    |   9 +-
 6 files changed, 300 insertions(+), 170 deletions(-)

diff --git a/.github/workflows/checks.yaml b/.github/workflows/checks.yaml
index ba000a7..3922bf1 100644
--- a/.github/workflows/checks.yaml
+++ b/.github/workflows/checks.yaml
@@ -2,7 +2,7 @@ name: Tests
 on: [push, pull_request]
 jobs:
   test:
-    runs-on: ubuntu-latest
+    runs-on: ubuntu-22.04
     strategy:
       matrix:
         db_url: ["http://localhost:8000", "postgres://postgres:postgres@localhost:5432/gene_normalizer_test"]
diff --git a/docs/source/normalizing_data/normalization.rst b/docs/source/normalizing_data/normalization.rst
index 84d245a..13aa83f 100644
--- a/docs/source/normalizing_data/normalization.rst
+++ b/docs/source/normalizing_data/normalization.rst
@@ -77,12 +77,13 @@ Normalized records are structured as `Genes <https://github.com/ga4gh/vrs/tree/2
           {
               "coding": {
                   "code": "HGNC:1097",
-                  "system": "https://www.genenames.org",
+                  "system": "https://www.genenames.org/data/gene-symbol-report/#!/hgnc_id/",
               },
               "relation": "exactMatch",
           },
           {
               "coding": {
+                  "id": "ncbigene:673",
                   "code": "673",
                   "system": "https://www.ncbi.nlm.nih.gov/gene/",
               },
@@ -90,76 +91,97 @@ Normalized records are structured as `Genes <https://github.com/ga4gh/vrs/tree/2
           },
           {
               "coding": {
+                  "id": "ensembl:ENSG00000157764",
                   "code": "ENSG00000157764",
-                  "system": "https://www.ensembl.org",
+                  "system": "https://www.ensembl.org/id/",
               },
               "relation": "relatedMatch",
           },
           {
               "coding": {
+                  "id": "iuphar:1943",
                   "code": "1943",
-                  "system": "https://www.guidetopharmacology.org",
+                  "system": "https://www.guidetopharmacology.org/GRAC/ObjectDisplayForward?objectId=",
               },
               "relation": "relatedMatch",
           },
           {
-              "coding": {"code": "119066", "system": "orphanet"},
+              "coding": {
+                  "id": "orphanet:119066",
+                  "code": "119066",
+                  "system": "http://www.orpha.net/consor/cgi-bin/OC_Exp.php?Lng=EN&Expert=",
+              },
               "relation": "relatedMatch",
           },
           {
               "coding": {
+                  "id": "cosmic:BRAF",
                   "code": "BRAF",
-                  "system": "https://cancer.sanger.ac.uk/cosmic",
+                  "system": "http://cancer.sanger.ac.uk/cosmic/gene/overview?ln=",
               },
               "relation": "relatedMatch",
           },
           {
               "coding": {
+                  "id": "pubmed:2284096",
                   "code": "2284096",
-                  "system": "https://pubmed.ncbi.nlm.nih.gov",
+                  "system": "https://pubmed.ncbi.nlm.nih.gov/",
               },
               "relation": "relatedMatch",
           },
           {
               "coding": {
+                  "id": "ucsc:uc003vwc.5",
                   "code": "uc003vwc.5",
-                  "system": "https://genome.ucsc.edu",
+                  "system": "http://genome.cse.ucsc.edu/cgi-bin/hgGene?org=Human&hgg_chrom=none&hgg_type=knownGene&hgg_gene=",
               },
               "relation": "relatedMatch",
           },
           {
-              "coding": {"code": "164757", "system": "https://www.omim.org"},
+              "coding": {
+                  "id": "omim:164757",
+                  "code": "164757",
+                  "system": "https://www.omim.org/MIM:",
+              },
               "relation": "relatedMatch",
           },
           {
               "coding": {
+                  "id": "refseq:NM_004333",
                   "code": "NM_004333",
-                  "system": "https://www.ncbi.nlm.nih.gov/refseq/",
+                  "system": "https://www.ncbi.nlm.nih.gov/nuccore/",
               },
               "relation": "relatedMatch",
           },
           {
               "coding": {
+                  "id": "uniprot:P15056",
                   "code": "P15056",
-                  "system": "https://www.uniprot.org",
+                  "system": "http://purl.uniprot.org/uniprot/",
               },
               "relation": "relatedMatch",
           },
           {
               "coding": {
+                  "id": "ena.embl:M95712",
                   "code": "M95712",
-                  "system": "https://www.ebi.ac.uk/ena/",
+                  "system": "https://www.ebi.ac.uk/ena/browser/view/",
               },
               "relation": "relatedMatch",
           },
           {
-              "coding": {"code": "OTTHUMG00000157457", "system": "vega"},
+              "coding": {
+                  "id": "vega:OTTHUMG00000157457",
+                  "code": "OTTHUMG00000157457",
+                  "system": "https://vega.archive.ensembl.org/Homo_sapiens/Gene/Summary?g=",
+              },
               "relation": "relatedMatch",
           },
           {
               "coding": {
+                  "id": "pubmed:1565476",
                   "code": "1565476",
-                  "system": "https://pubmed.ncbi.nlm.nih.gov",
+                  "system": "https://pubmed.ncbi.nlm.nih.gov/",
               },
               "relation": "relatedMatch",
           },
diff --git a/src/gene/query.py b/src/gene/query.py
index 238b8e1..570fc41 100644
--- a/src/gene/query.py
+++ b/src/gene/query.py
@@ -21,7 +21,6 @@
 from gene.database import AbstractDatabase, DatabaseReadException
 from gene.schemas import (
     NAMESPACE_TO_SYSTEM_URI,
-    SYSTEM_URI_TO_NAMESPACE,
     BaseGene,
     BaseNormalizationService,
     Gene,
@@ -348,7 +347,7 @@ def _add_merged_meta(self, response: NormalizeService) -> NormalizeService:
 
         sources = []
         for m in gene.mappings or []:
-            ns = SYSTEM_URI_TO_NAMESPACE.get(m.coding.system)
+            ns = m.coding.id.split(":")[0]
             if ns in PREFIX_LOOKUP:
                 sources.append(PREFIX_LOOKUP[ns])
 
@@ -406,8 +405,7 @@ def _create_concept_mapping(
         ) -> ConceptMapping:
             """Create concept mapping for identifier
 
-            ``system`` will use source homepage or namespace prefix, in that order of \
-            preference, if available.
+            ``system`` will use system prefix URL or system homepage
 
             :param concept_id: A lowercase concept identifier represented as a curie
             :param relation: SKOS mapping relationship, default is relatedMatch
@@ -415,7 +413,7 @@ def _create_concept_mapping(
                 ``NamespacePrefix``
             :return: Concept mapping for identifier
             """
-            source = concept_id.split(":")[0]
+            source, source_code = concept_id.split(":")
 
             try:
                 source = NamespacePrefix(source)
@@ -423,10 +421,16 @@ def _create_concept_mapping(
                 err_msg = f"Namespace prefix not supported: {source}"
                 raise ValueError(err_msg) from e
 
-            system = NAMESPACE_TO_SYSTEM_URI.get(source, source)
+            if source == NamespacePrefix.HGNC:
+                source_code = concept_id.upper()
 
             return ConceptMapping(
-                coding=Coding(code=code(concept_id), system=system), relation=relation
+                coding=Coding(
+                    id=concept_id,
+                    code=code(source_code),
+                    system=NAMESPACE_TO_SYSTEM_URI[source],
+                ),
+                relation=relation,
             )
 
         gene_obj = MappableConcept(
diff --git a/src/gene/schemas.py b/src/gene/schemas.py
index 9275dac..dfc6adf 100644
--- a/src/gene/schemas.py
+++ b/src/gene/schemas.py
@@ -169,7 +169,6 @@ class NamespacePrefix(Enum):
     HORDE = "hordedb"
     MEROPS = "merops"
     IUPHAR = "iuphar"
-    KZNF = "knzfgc"
     MAMIT = "mamittrnadb"
     CD = "hcdmdb"
     LNCRNADB = "lncrnadb"
@@ -178,31 +177,35 @@ class NamespacePrefix(Enum):
     RFAM = "rfam"
 
 
-# Source to URI. Will use source homepage
+# Source to URI. Will use system URI prefix or system homepage
 NAMESPACE_TO_SYSTEM_URI: dict[NamespacePrefix, str] = {
-    NamespacePrefix.HGNC: "https://www.genenames.org",
-    NamespacePrefix.ENSEMBL: "https://www.ensembl.org",
+    NamespacePrefix.HGNC: "https://www.genenames.org/data/gene-symbol-report/#!/hgnc_id/",
+    NamespacePrefix.ENSEMBL: "https://www.ensembl.org/id/",
     NamespacePrefix.NCBI: "https://www.ncbi.nlm.nih.gov/gene/",
     NamespacePrefix.ENTREZ: "https://www.ncbi.nlm.nih.gov/gene/",
-    NamespacePrefix.VEGA: "https://www.sanger.ac.uk/tool/vega-genome-browser/",
-    NamespacePrefix.UCSC: "https://genome.ucsc.edu",
-    NamespacePrefix.ENA: "https://www.ebi.ac.uk/ena/",
-    NamespacePrefix.REFSEQ: "https://www.ncbi.nlm.nih.gov/refseq/",
-    NamespacePrefix.CCDS: "https://www.ncbi.nlm.nih.gov/projects/CCDS/CcdsBrowse.cgi",
-    NamespacePrefix.UNIPROT: "https://www.uniprot.org",
-    NamespacePrefix.PUBMED: "https://pubmed.ncbi.nlm.nih.gov",
-    NamespacePrefix.COSMIC: "https://cancer.sanger.ac.uk/cosmic/",
-    NamespacePrefix.OMIM: "https://www.omim.org",
-    NamespacePrefix.SNORNABASE: "https://www-snorna.biotoul.fr",
-    NamespacePrefix.PSEUDOGENE: "http://pseudogene.org",
-    NamespacePrefix.MEROPS: "https://www.ebi.ac.uk/merops/",
-    NamespacePrefix.IUPHAR: "https://www.guidetopharmacology.org",
-    NamespacePrefix.RFAM: "https://rfam.org",
-}
-
-# URI to source
-SYSTEM_URI_TO_NAMESPACE = {
-    system_uri: ns.value for ns, system_uri in NAMESPACE_TO_SYSTEM_URI.items()
+    NamespacePrefix.VEGA: "https://vega.archive.ensembl.org/Homo_sapiens/Gene/Summary?g=",
+    NamespacePrefix.UCSC: "http://genome.cse.ucsc.edu/cgi-bin/hgGene?org=Human&hgg_chrom=none&hgg_type=knownGene&hgg_gene=",
+    NamespacePrefix.ENA: "https://www.ebi.ac.uk/ena/browser/view/",
+    NamespacePrefix.REFSEQ: "https://www.ncbi.nlm.nih.gov/nuccore/",
+    NamespacePrefix.CCDS: "http://www.ncbi.nlm.nih.gov/CCDS/CcdsBrowse.cgi?REQUEST=CCDS&DATA=",
+    NamespacePrefix.UNIPROT: "http://purl.uniprot.org/uniprot/",
+    NamespacePrefix.PUBMED: "https://pubmed.ncbi.nlm.nih.gov/",
+    NamespacePrefix.COSMIC: "http://cancer.sanger.ac.uk/cosmic/gene/overview?ln=",
+    NamespacePrefix.OMIM: "https://www.omim.org/MIM:",
+    NamespacePrefix.MIRBASE: "https://mirbase.org/hairpin/",
+    NamespacePrefix.HOMEODB: "http://homeodb.zoo.ox.ac.uk",
+    NamespacePrefix.SNORNABASE: "http://www-snorna.biotoul.fr/plus.php?id=",
+    NamespacePrefix.ORPHANET: "http://www.orpha.net/consor/cgi-bin/OC_Exp.php?Lng=EN&Expert=",
+    NamespacePrefix.PSEUDOGENE: "http://tables.pseudogene.org/",
+    NamespacePrefix.HORDE: "http://genome.weizmann.ac.il/horde/card/index/symbol:",
+    NamespacePrefix.MEROPS: "https://www.ebi.ac.uk/merops/cgi-bin/pepsum?id=",
+    NamespacePrefix.IUPHAR: "https://www.guidetopharmacology.org/GRAC/ObjectDisplayForward?objectId=",
+    NamespacePrefix.MAMIT: "http://mamit-trna.u-strasbg.fr/mutations.asp?idAA=",
+    NamespacePrefix.CD: "http://www.hcdm.org/index.php?option=com_molecule&cdnumber=",
+    NamespacePrefix.IMGT: "https://www.imgt.org/genedb/GENElect?species=Homo+sapiens&query=2+",
+    NamespacePrefix.IMGT_GENE_DB: "https://www.imgt.org/genedb/GENElect?species=Homo+sapiens&query=2+",
+    NamespacePrefix.LNCRNADB: "https://rnacentral.org/rna/",
+    NamespacePrefix.RFAM: "https://rfam.org/family/",
 }
 
 
@@ -347,96 +350,113 @@ class NormalizeService(BaseNormalizationService):
                     "mappings": [
                         {
                             "coding": {
-                                "code": "hgnc:1097",
-                                "system": "https://www.genenames.org",
+                                "id": "hgnc:1097",
+                                "code": "HGNC:1097",
+                                "system": "https://www.genenames.org/data/gene-symbol-report/#!/hgnc_id/",
                             },
                             "relation": "exactMatch",
                         },
                         {
                             "coding": {
-                                "code": "ncbigene:673",
+                                "id": "ncbigene:673",
+                                "code": "673",
                                 "system": "https://www.ncbi.nlm.nih.gov/gene/",
                             },
                             "relation": "relatedMatch",
                         },
                         {
                             "coding": {
-                                "code": "ensembl:ENSG00000157764",
-                                "system": "https://www.ensembl.org",
+                                "id": "ensembl:ENSG00000157764",
+                                "code": "ENSG00000157764",
+                                "system": "https://www.ensembl.org/id/",
                             },
                             "relation": "relatedMatch",
                         },
                         {
                             "coding": {
-                                "code": "iuphar:1943",
-                                "system": "https://www.guidetopharmacology.org",
+                                "id": "iuphar:1943",
+                                "code": "1943",
+                                "system": "https://www.guidetopharmacology.org/GRAC/ObjectDisplayForward?objectId=",
                             },
                             "relation": "relatedMatch",
                         },
                         {
-                            "coding": {"code": "orphanet:119066", "system": "orphanet"},
+                            "coding": {
+                                "id": "orphanet:119066",
+                                "code": "119066",
+                                "system": "http://www.orpha.net/consor/cgi-bin/OC_Exp.php?Lng=EN&Expert=",
+                            },
                             "relation": "relatedMatch",
                         },
                         {
                             "coding": {
-                                "code": "cosmic:BRAF",
-                                "system": "https://cancer.sanger.ac.uk/cosmic",
+                                "id": "cosmic:BRAF",
+                                "code": "BRAF",
+                                "system": "http://cancer.sanger.ac.uk/cosmic/gene/overview?ln=",
                             },
                             "relation": "relatedMatch",
                         },
                         {
                             "coding": {
-                                "code": "pubmed:2284096",
-                                "system": "https://pubmed.ncbi.nlm.nih.gov",
+                                "id": "pubmed:2284096",
+                                "code": "2284096",
+                                "system": "https://pubmed.ncbi.nlm.nih.gov/",
                             },
                             "relation": "relatedMatch",
                         },
                         {
                             "coding": {
-                                "code": "ucsc:uc003vwc.5",
-                                "system": "https://genome.ucsc.edu",
+                                "id": "ucsc:uc003vwc.5",
+                                "code": "uc003vwc.5",
+                                "system": "http://genome.cse.ucsc.edu/cgi-bin/hgGene?org=Human&hgg_chrom=none&hgg_type=knownGene&hgg_gene=",
                             },
                             "relation": "relatedMatch",
                         },
                         {
                             "coding": {
-                                "code": "omim:164757",
-                                "system": "https://www.omim.org",
+                                "id": "omim:164757",
+                                "code": "164757",
+                                "system": "https://www.omim.org/MIM:",
                             },
                             "relation": "relatedMatch",
                         },
                         {
                             "coding": {
-                                "code": "refseq:NM_004333",
-                                "system": "https://www.ncbi.nlm.nih.gov/refseq/",
+                                "id": "refseq:NM_004333",
+                                "code": "NM_004333",
+                                "system": "https://www.ncbi.nlm.nih.gov/nuccore/",
                             },
                             "relation": "relatedMatch",
                         },
                         {
                             "coding": {
-                                "code": "uniprot:P15056",
-                                "system": "https://www.uniprot.org",
+                                "id": "uniprot:P15056",
+                                "code": "P15056",
+                                "system": "http://purl.uniprot.org/uniprot/",
                             },
                             "relation": "relatedMatch",
                         },
                         {
                             "coding": {
-                                "code": "ena.embl:M95712",
-                                "system": "https://www.ebi.ac.uk/ena/",
+                                "id": "ena.embl:M95712",
+                                "code": "M95712",
+                                "system": "https://www.ebi.ac.uk/ena/browser/view/",
                             },
                             "relation": "relatedMatch",
                         },
                         {
                             "coding": {
-                                "code": "vega:OTTHUMG00000157457",
-                                "system": "vega",
+                                "id": "vega:OTTHUMG00000157457",
+                                "code": "OTTHUMG00000157457",
+                                "system": "https://vega.archive.ensembl.org/Homo_sapiens/Gene/Summary?g=",
                             },
                             "relation": "relatedMatch",
                         },
                         {
                             "coding": {
-                                "code": "pubmed:1565476",
-                                "system": "https://pubmed.ncbi.nlm.nih.gov",
+                                "id": "pubmed:1565476",
+                                "code": "1565476",
+                                "system": "https://pubmed.ncbi.nlm.nih.gov/",
                             },
                             "relation": "relatedMatch",
                         },
diff --git a/tests/unit/test_query.py b/tests/unit/test_query.py
index 5414365..a7250e3 100644
--- a/tests/unit/test_query.py
+++ b/tests/unit/test_query.py
@@ -39,75 +39,89 @@ def normalized_ache():
         "mappings": [
             {
                 "coding": {
-                    "code": "hgnc:108",
-                    "system": "https://www.genenames.org",
+                    "id": "hgnc:108",
+                    "code": "HGNC:108",
+                    "system": "https://www.genenames.org/data/gene-symbol-report/#!/hgnc_id/",
                 },
                 "relation": "exactMatch",
             },
             {
                 "coding": {
-                    "code": "ensembl:ENSG00000087085",
-                    "system": "https://www.ensembl.org",
+                    "id": "ensembl:ENSG00000087085",
+                    "code": "ENSG00000087085",
+                    "system": "https://www.ensembl.org/id/",
                 },
                 "relation": "relatedMatch",
             },
             {
                 "coding": {
-                    "code": "ncbigene:43",
+                    "id": "ncbigene:43",
+                    "code": "43",
                     "system": "https://www.ncbi.nlm.nih.gov/gene/",
                 },
                 "relation": "relatedMatch",
             },
             {
                 "coding": {
-                    "code": "vega:OTTHUMG00000157033",
-                    "system": "https://www.sanger.ac.uk/tool/vega-genome-browser/",
+                    "id": "vega:OTTHUMG00000157033",
+                    "code": "OTTHUMG00000157033",
+                    "system": "https://vega.archive.ensembl.org/Homo_sapiens/Gene/Summary?g=",
                 },
                 "relation": "relatedMatch",
             },
             {
                 "coding": {
-                    "code": "ucsc:uc003uxi.4",
-                    "system": "https://genome.ucsc.edu",
+                    "id": "ucsc:uc003uxi.4",
+                    "code": "uc003uxi.4",
+                    "system": "http://genome.cse.ucsc.edu/cgi-bin/hgGene?org=Human&hgg_chrom=none&hgg_type=knownGene&hgg_gene=",
                 },
                 "relation": "relatedMatch",
             },
             {
                 "coding": {
-                    "code": "uniprot:P22303",
-                    "system": "https://www.uniprot.org",
+                    "id": "uniprot:P22303",
+                    "code": "P22303",
+                    "system": "http://purl.uniprot.org/uniprot/",
                 },
                 "relation": "relatedMatch",
             },
             {
                 "coding": {
-                    "code": "pubmed:1380483",
-                    "system": "https://pubmed.ncbi.nlm.nih.gov",
+                    "id": "pubmed:1380483",
+                    "code": "1380483",
+                    "system": "https://pubmed.ncbi.nlm.nih.gov/",
                 },
                 "relation": "relatedMatch",
             },
             {
-                "coding": {"code": "omim:100740", "system": "https://www.omim.org"},
+                "coding": {
+                    "id": "omim:100740",
+                    "code": "100740",
+                    "system": "https://www.omim.org/MIM:",
+                },
                 "relation": "relatedMatch",
             },
             {
                 "coding": {
-                    "code": "merops:S09.979",
-                    "system": "https://www.ebi.ac.uk/merops/",
+                    "id": "merops:S09.979",
+                    "code": "S09.979",
+                    "system": "https://www.ebi.ac.uk/merops/cgi-bin/pepsum?id=",
                 },
                 "relation": "relatedMatch",
             },
             {
                 "coding": {
-                    "code": "iuphar:2465",
-                    "system": "https://www.guidetopharmacology.org",
+                    "id": "iuphar:2465",
+                    "code": "2465",
+                    "system": "https://www.guidetopharmacology.org/GRAC/ObjectDisplayForward?objectId=",
                 },
                 "relation": "relatedMatch",
             },
             {
                 "coding": {
-                    "code": "refseq:NM_015831",
-                    "system": "https://www.ncbi.nlm.nih.gov/refseq/",
+                    "id": "refseq:NM_015831",
+                    "code": "NM_015831",
+                    "system": "https://www.ncbi.nlm.nih.gov/nuccore/",
                 },
                 "relation": "relatedMatch",
             },
@@ -171,93 +185,113 @@ def normalized_braf():
         "mappings": [
             {
                 "coding": {
-                    "code": "hgnc:1097",
-                    "system": "https://www.genenames.org",
+                    "id": "hgnc:1097",
+                    "code": "HGNC:1097",
+                    "system": "https://www.genenames.org/data/gene-symbol-report/#!/hgnc_id/",
                 },
                 "relation": "exactMatch",
             },
             {
                 "coding": {
-                    "code": "ncbigene:673",
+                    "id": "ncbigene:673",
+                    "code": "673",
                     "system": "https://www.ncbi.nlm.nih.gov/gene/",
                 },
                 "relation": "relatedMatch",
             },
             {
                 "coding": {
-                    "code": "ensembl:ENSG00000157764",
-                    "system": "https://www.ensembl.org",
+                    "id": "ensembl:ENSG00000157764",
+                    "code": "ENSG00000157764",
+                    "system": "https://www.ensembl.org/id/",
                 },
                 "relation": "relatedMatch",
             },
             {
                 "coding": {
-                    "code": "iuphar:1943",
-                    "system": "https://www.guidetopharmacology.org",
+                    "id": "iuphar:1943",
+                    "code": "1943",
+                    "system": "https://www.guidetopharmacology.org/GRAC/ObjectDisplayForward?objectId=",
                 },
                 "relation": "relatedMatch",
             },
             {
-                "coding": {"code": "orphanet:119066", "system": "orphanet"},
+                "coding": {
+                    "id": "orphanet:119066",
+                    "code": "119066",
+                    "system": "http://www.orpha.net/consor/cgi-bin/OC_Exp.php?Lng=EN&Expert=",
+                },
                 "relation": "relatedMatch",
             },
             {
                 "coding": {
-                    "code": "cosmic:BRAF",
-                    "system": "https://cancer.sanger.ac.uk/cosmic/",
+                    "id": "cosmic:BRAF",
+                    "code": "BRAF",
+                    "system": "http://cancer.sanger.ac.uk/cosmic/gene/overview?ln=",
                 },
                 "relation": "relatedMatch",
             },
             {
                 "coding": {
-                    "code": "pubmed:2284096",
-                    "system": "https://pubmed.ncbi.nlm.nih.gov",
+                    "id": "pubmed:2284096",
+                    "code": "2284096",
+                    "system": "https://pubmed.ncbi.nlm.nih.gov/",
                 },
                 "relation": "relatedMatch",
             },
             {
                 "coding": {
-                    "code": "ucsc:uc003vwc.5",
-                    "system": "https://genome.ucsc.edu",
+                    "id": "ucsc:uc003vwc.5",
+                    "code": "uc003vwc.5",
+                    "system": "http://genome.cse.ucsc.edu/cgi-bin/hgGene?org=Human&hgg_chrom=none&hgg_type=knownGene&hgg_gene=",
                 },
                 "relation": "relatedMatch",
             },
             {
-                "coding": {"code": "omim:164757", "system": "https://www.omim.org"},
+                "coding": {
+                    "id": "omim:164757",
+                    "code": "164757",
+                    "system": "https://www.omim.org/MIM:",
+                },
                 "relation": "relatedMatch",
             },
             {
                 "coding": {
-                    "code": "refseq:NM_004333",
-                    "system": "https://www.ncbi.nlm.nih.gov/refseq/",
+                    "id": "refseq:NM_004333",
+                    "code": "NM_004333",
+                    "system": "https://www.ncbi.nlm.nih.gov/nuccore/",
                 },
                 "relation": "relatedMatch",
             },
             {
                 "coding": {
-                    "code": "uniprot:P15056",
-                    "system": "https://www.uniprot.org",
+                    "id": "uniprot:P15056",
+                    "code": "P15056",
+                    "system": "http://purl.uniprot.org/uniprot/",
                 },
                 "relation": "relatedMatch",
             },
             {
                 "coding": {
-                    "code": "ena.embl:M95712",
-                    "system": "https://www.ebi.ac.uk/ena/",
+                    "id": "ena.embl:M95712",
+                    "code": "M95712",
+                    "system": "https://www.ebi.ac.uk/ena/browser/view/",
                 },
                 "relation": "relatedMatch",
             },
             {
                 "coding": {
-                    "code": "vega:OTTHUMG00000157457",
-                    "system": "https://www.sanger.ac.uk/tool/vega-genome-browser/",
+                    "id": "vega:OTTHUMG00000157457",
+                    "code": "OTTHUMG00000157457",
+                    "system": "https://vega.archive.ensembl.org/Homo_sapiens/Gene/Summary?g=",
                 },
                 "relation": "relatedMatch",
             },
             {
                 "coding": {
-                    "code": "pubmed:1565476",
-                    "system": "https://pubmed.ncbi.nlm.nih.gov",
+                    "id": "pubmed:1565476",
+                    "code": "1565476",
+                    "system": "https://pubmed.ncbi.nlm.nih.gov/",
                 },
                 "relation": "relatedMatch",
             },
@@ -323,93 +357,113 @@ def normalized_abl1():
         "mappings": [
             {
                 "coding": {
-                    "code": "hgnc:76",
-                    "system": "https://www.genenames.org",
+                    "id": "hgnc:76",
+                    "code": "HGNC:76",
+                    "system": "https://www.genenames.org/data/gene-symbol-report/#!/hgnc_id/",
                 },
                 "relation": "exactMatch",
             },
             {
                 "coding": {
-                    "code": "ensembl:ENSG00000097007",
-                    "system": "https://www.ensembl.org",
+                    "id": "ensembl:ENSG00000097007",
+                    "code": "ENSG00000097007",
+                    "system": "https://www.ensembl.org/id/",
                 },
                 "relation": "relatedMatch",
             },
             {
                 "coding": {
-                    "code": "ncbigene:25",
+                    "id": "ncbigene:25",
+                    "code": "25",
                     "system": "https://www.ncbi.nlm.nih.gov/gene/",
                 },
                 "relation": "relatedMatch",
             },
             {
                 "coding": {
-                    "code": "vega:OTTHUMG00000020813",
-                    "system": "https://www.sanger.ac.uk/tool/vega-genome-browser/",
+                    "id": "vega:OTTHUMG00000020813",
+                    "code": "OTTHUMG00000020813",
+                    "system": "https://vega.archive.ensembl.org/Homo_sapiens/Gene/Summary?g=",
                 },
                 "relation": "relatedMatch",
             },
             {
                 "coding": {
-                    "code": "ucsc:uc004bzv.4",
-                    "system": "https://genome.ucsc.edu",
+                    "id": "ucsc:uc004bzv.4",
+                    "code": "uc004bzv.4",
+                    "system": "http://genome.cse.ucsc.edu/cgi-bin/hgGene?org=Human&hgg_chrom=none&hgg_type=knownGene&hgg_gene=",
                 },
                 "relation": "relatedMatch",
             },
             {
                 "coding": {
-                    "code": "uniprot:P00519",
-                    "system": "https://www.uniprot.org",
+                    "id": "uniprot:P00519",
+                    "code": "P00519",
+                    "system": "http://purl.uniprot.org/uniprot/",
                 },
                 "relation": "relatedMatch",
             },
             {
                 "coding": {
-                    "code": "pubmed:1857987",
-                    "system": "https://pubmed.ncbi.nlm.nih.gov",
+                    "id": "pubmed:1857987",
+                    "code": "1857987",
+                    "system": "https://pubmed.ncbi.nlm.nih.gov/",
                 },
                 "relation": "relatedMatch",
             },
             {
                 "coding": {
-                    "code": "pubmed:12626632",
-                    "system": "https://pubmed.ncbi.nlm.nih.gov",
+                    "id": "pubmed:12626632",
+                    "code": "12626632",
+                    "system": "https://pubmed.ncbi.nlm.nih.gov/",
                 },
                 "relation": "relatedMatch",
             },
             {
                 "coding": {
-                    "code": "cosmic:ABL1",
-                    "system": "https://cancer.sanger.ac.uk/cosmic/",
+                    "id": "cosmic:ABL1",
+                    "code": "ABL1",
+                    "system": "http://cancer.sanger.ac.uk/cosmic/gene/overview?ln=",
                 },
                 "relation": "relatedMatch",
             },
             {
-                "coding": {"code": "omim:189980", "system": "https://www.omim.org"},
+                "coding": {
+                    "id": "omim:189980",
+                    "code": "189980",
+                    "system": "https://www.omim.org/MIM:",
+                },
                 "relation": "relatedMatch",
             },
             {
-                "coding": {"code": "orphanet:117691", "system": "orphanet"},
+                "coding": {
+                    "id": "orphanet:117691",
+                    "code": "117691",
+                    "system": "http://www.orpha.net/consor/cgi-bin/OC_Exp.php?Lng=EN&Expert=",
+                },
                 "relation": "relatedMatch",
             },
             {
                 "coding": {
-                    "code": "iuphar:1923",
-                    "system": "https://www.guidetopharmacology.org",
+                    "id": "iuphar:1923",
+                    "code": "1923",
+                    "system": "https://www.guidetopharmacology.org/GRAC/ObjectDisplayForward?objectId=",
                 },
                 "relation": "relatedMatch",
             },
             {
                 "coding": {
-                    "code": "ena.embl:M14752",
-                    "system": "https://www.ebi.ac.uk/ena/",
+                    "id": "ena.embl:M14752",
+                    "code": "M14752",
+                    "system": "https://www.ebi.ac.uk/ena/browser/view/",
                 },
                 "relation": "relatedMatch",
             },
             {
                 "coding": {
-                    "code": "refseq:NM_007313",
-                    "system": "https://www.ncbi.nlm.nih.gov/refseq/",
+                    "id": "refseq:NM_007313",
+                    "code": "NM_007313",
+                    "system": "https://www.ncbi.nlm.nih.gov/nuccore/",
                 },
                 "relation": "relatedMatch",
             },
@@ -491,75 +545,89 @@ def normalized_p150():
         "mappings": [
             {
                 "coding": {
-                    "code": "hgnc:1910",
-                    "system": "https://www.genenames.org",
+                    "id": "hgnc:1910",
+                    "code": "HGNC:1910",
+                    "system": "https://www.genenames.org/data/gene-symbol-report/#!/hgnc_id/",
                 },
                 "relation": "exactMatch",
             },
             {
                 "coding": {
-                    "code": "ensembl:ENSG00000167670",
-                    "system": "https://www.ensembl.org",
+                    "id": "ensembl:ENSG00000167670",
+                    "code": "ENSG00000167670",
+                    "system": "https://www.ensembl.org/id/",
                 },
                 "relation": "relatedMatch",
             },
             {
                 "coding": {
-                    "code": "ncbigene:10036",
+                    "id": "ncbigene:10036",
+                    "code": "10036",
                     "system": "https://www.ncbi.nlm.nih.gov/gene/",
                 },
                 "relation": "relatedMatch",
             },
             {
-                "coding": {"code": "omim:601246", "system": "https://www.omim.org"},
+                "coding": {
+                    "id": "omim:601246",
+                    "code": "601246",
+                    "system": "https://www.omim.org/MIM:",
+                },
                 "relation": "relatedMatch",
             },
             {
                 "coding": {
-                    "code": "ccds:CCDS32875",
-                    "system": "https://www.ncbi.nlm.nih.gov/projects/CCDS/CcdsBrowse.cgi",
+                    "id": "ccds:CCDS32875",
+                    "code": "CCDS32875",
+                    "system": "http://www.ncbi.nlm.nih.gov/CCDS/CcdsBrowse.cgi?REQUEST=CCDS&DATA=",
                 },
                 "relation": "relatedMatch",
             },
             {
                 "coding": {
-                    "code": "pubmed:7600578",
-                    "system": "https://pubmed.ncbi.nlm.nih.gov",
+                    "id": "pubmed:7600578",
+                    "code": "7600578",
+                    "system": "https://pubmed.ncbi.nlm.nih.gov/",
                 },
                 "relation": "relatedMatch",
             },
             {
                 "coding": {
-                    "code": "vega:OTTHUMG00000181922",
-                    "system": "https://www.sanger.ac.uk/tool/vega-genome-browser/",
+                    "id": "vega:OTTHUMG00000181922",
+                    "code": "OTTHUMG00000181922",
+                    "system": "https://vega.archive.ensembl.org/Homo_sapiens/Gene/Summary?g=",
                 },
                 "relation": "relatedMatch",
             },
             {
                 "coding": {
-                    "code": "uniprot:Q13111",
-                    "system": "https://www.uniprot.org",
+                    "id": "uniprot:Q13111",
+                    "code": "Q13111",
+                    "system": "http://purl.uniprot.org/uniprot/",
                 },
                 "relation": "relatedMatch",
             },
             {
                 "coding": {
-                    "code": "refseq:NM_005483",
-                    "system": "https://www.ncbi.nlm.nih.gov/refseq/",
+                    "id": "refseq:NM_005483",
+                    "code": "NM_005483",
+                    "system": "https://www.ncbi.nlm.nih.gov/nuccore/",
                 },
                 "relation": "relatedMatch",
             },
             {
                 "coding": {
-                    "code": "ena.embl:U20979",
-                    "system": "https://www.ebi.ac.uk/ena/",
+                    "id": "ena.embl:U20979",
+                    "code": "U20979",
+                    "system": "https://www.ebi.ac.uk/ena/browser/view/",
                 },
                 "relation": "relatedMatch",
             },
             {
                 "coding": {
-                    "code": "ucsc:uc002mal.4",
-                    "system": "https://genome.ucsc.edu",
+                    "id": "ucsc:uc002mal.4",
+                    "code": "uc002mal.4",
+                    "system": "http://genome.cse.ucsc.edu/cgi-bin/hgGene?org=Human&hgg_chrom=none&hgg_type=knownGene&hgg_gene=",
                 },
                 "relation": "relatedMatch",
             },
@@ -638,7 +706,8 @@ def normalized_loc_653303():
         "mappings": [
             {
                 "coding": {
-                    "code": "ncbigene:653303",
+                    "id": "ncbigene:653303",
+                    "code": "653303",
                     "system": "https://www.ncbi.nlm.nih.gov/gene/",
                 },
                 "relation": "exactMatch",
@@ -923,33 +992,41 @@ def normalized_ifnr():
         "mappings": [
             {
                 "coding": {
-                    "code": "hgnc:5447",
-                    "system": "https://www.genenames.org",
+                    "id": "hgnc:5447",
+                    "code": "HGNC:5447",
+                    "system": "https://www.genenames.org/data/gene-symbol-report/#!/hgnc_id/",
                 },
                 "relation": "exactMatch",
             },
             {
                 "coding": {
-                    "code": "ncbigene:3466",
+                    "id": "ncbigene:3466",
+                    "code": "3466",
                     "system": "https://www.ncbi.nlm.nih.gov/gene/",
                 },
                 "relation": "relatedMatch",
             },
             {
                 "coding": {
-                    "code": "pubmed:1906174",
-                    "system": "https://pubmed.ncbi.nlm.nih.gov",
+                    "id": "pubmed:1906174",
+                    "code": "1906174",
+                    "system": "https://pubmed.ncbi.nlm.nih.gov/",
                 },
                 "relation": "relatedMatch",
             },
             {
-                "coding": {"code": "omim:147573", "system": "https://www.omim.org"},
+                "coding": {
+                    "id": "omim:147573",
+                    "code": "147573",
+                    "system": "https://www.omim.org/MIM:",
+                },
                 "relation": "relatedMatch",
             },
             {
                 "coding": {
-                    "code": "pubmed:1193239",
-                    "system": "https://pubmed.ncbi.nlm.nih.gov",
+                    "id": "pubmed:1193239",
+                    "code": "1193239",
+                    "system": "https://pubmed.ncbi.nlm.nih.gov/",
                 },
                 "relation": "relatedMatch",
             },
diff --git a/tests/unit/test_schemas.py b/tests/unit/test_schemas.py
index 7dbc2a5..f367112 100644
--- a/tests/unit/test_schemas.py
+++ b/tests/unit/test_schemas.py
@@ -4,7 +4,7 @@
 import pytest
 from ga4gh.vrs.models import SequenceLocation, SequenceReference
 
-from gene.schemas import Gene
+from gene.schemas import NAMESPACE_TO_SYSTEM_URI, Gene, NamespacePrefix
 
 
 @pytest.fixture(scope="module")
@@ -104,3 +104,10 @@ def test_gene(gene, sequence_location):
             symbol="BRAF",
             locations=sequence_location,
         )
+
+
+def test_namespace_to_system_uri():
+    """Ensure that each NamespacePrefix is included in NAMESPACE_TO_SYSTEM_URI"""
+    for v in NamespacePrefix.__members__.values():
+        assert v in NAMESPACE_TO_SYSTEM_URI, v
+        assert NAMESPACE_TO_SYSTEM_URI[v].startswith("http"), v