Add clique leaders option - #350

Draft
gaurav wants to merge 37 commits into
mainfrom
add-clique-leaders-option
Draft

Add clique leaders option#350
gaurav wants to merge 37 commits into
mainfrom
add-clique-leaders-option

Conversation

@gaurav

@gauravgaurav commented Dec 15, 2025

Copy link
Copy Markdown
Collaborator

This PR closes#320 by adding an include_clique_leaders option on normalization. This may be a way to fix#340. Also renames some variables and adds some LLM-generated function documentation.

This PR adds a new flag include_clique_leaders that can be set on both GET and POST /get_normalized_nodes endpoints. Activating this endpoint adds a clique_leaders key to each normalized identifier that includes a list of all the clique leaders in this clique, along with their name, type and taxa, and (if the appropriate flags are turned on) descriptions. This doesn't currently include all the identifiers in each clique, but that should be added without too much extra bother.

WIP

  • Would it be useful to include the list of identifiers for each clique leader? That will require some additional finagling with the code, but it shouldn't be too problematic.
  • Is clique_leaders really the best thing to call this thing? These are all clique leader identifiers, but maybe conflation_leaders or something else would be better?
  • Add tests to Babel Validator

Example

Example output for NCBIGene:1756 is included below. Note that the conflation type is included (e.g. "conflation": "GeneProtein") and that clique_leaders is a list of the cliques leaders ordered in their position in the normalization.

{
"NCBIGene:1756": {
"id": {
"identifier": "NCBIGene:1756",
"label": "DMD",
"description": "dystrophin"
},
"equivalent_identifiers": [
{
"identifier": "NCBIGene:1756",
"label": "DMD",
"description": "dystrophin",
"taxa": [
"NCBITaxon:9606"
],
"type": "biolink:Gene"
},
{
"identifier": "ENSEMBL:ENSG00000198947",
"type": "biolink:Gene"
},
{
"identifier": "HGNC:2928",
"label": "DMD",
"type": "biolink:Gene"
},
{
"identifier": "OMIM:300377",
"type": "biolink:Gene"
},
{
"identifier": "UMLS:C1414083",
"label": "DMD gene",
"type": "biolink:Gene"
},
{
"identifier": "UniProtKB:A0A087WV90",
"label": "A0A087WV90_HUMAN Dystrophin (trembl)",
"taxa": [
"NCBITaxon:9606"
],
"type": "biolink:Protein"
},
{
"identifier": "UniProtKB:A0A0S2Z3B5",
"label": "A0A0S2Z3B5_HUMAN Dystrophin isoform 2 (trembl)",
"taxa": [
"NCBITaxon:9606"
],
"type": "biolink:Protein"
},
{
"identifier": "UniProtKB:A0A0S2Z3J7",
"label": "A0A0S2Z3J7_HUMAN Dystrophin isoform 1 (Fragment) (trembl)",
"taxa": [
"NCBITaxon:9606"
],
"type": "biolink:Protein"
},
{
"identifier": "UniProtKB:A0A5H1ZRP9",
"label": "A0A5H1ZRP9_HUMAN Dystrophin (trembl)",
"taxa": [
"NCBITaxon:9606"
],
"type": "biolink:Protein"
},
{
"identifier": "UniProtKB:A0A5H1ZRQ1",
"label": "A0A5H1ZRQ1_HUMAN Dystrophin (trembl)",
"taxa": [
"NCBITaxon:9606"
],
"type": "biolink:Protein"
},
{
"identifier": "UniProtKB:A0A5H1ZRQ8",
"label": "A0A5H1ZRQ8_HUMAN Dystrophin (trembl)",
"taxa": [
"NCBITaxon:9606"
],
"type": "biolink:Protein"
},
{
"identifier": "UniProtKB:A0A5H1ZRR9",
"label": "A0A5H1ZRR9_HUMAN Dystrophin (trembl)",
"taxa": [
"NCBITaxon:9606"
],
"type": "biolink:Protein"
},
{
"identifier": "UniProtKB:A0A804HKY9",
"label": "A0A804HKY9_HUMAN Dystrophin (trembl)",
"taxa": [
"NCBITaxon:9606"
],
"type": "biolink:Protein"
},
{
"identifier": "UniProtKB:A7E212",
"label": "A7E212_HUMAN Dystrophin (trembl)",
"taxa": [
"NCBITaxon:9606"
],
"type": "biolink:Protein"
},
{
"identifier": "UniProtKB:P11532",
"label": "DMD_HUMAN Dystrophin (sprot)",
"taxa": [
"NCBITaxon:9606"
],
"type": "biolink:Protein"
},
{
"identifier": "PR:P11532",
"label": "dystrophin (human)",
"description": "A dystrophin that is encoded in the genome of human.",
"type": "biolink:Protein"
},
{
"identifier": "UMLS:C1437024",
"label": "DMD protein, human",
"type": "biolink:Protein"
},
{
"identifier": "MESH:C484258",
"label": "DMD protein, human",
"type": "biolink:Protein"
},
{
"identifier": "UniProtKB:Q16484",
"label": "Q16484_HUMAN DMD protein (Fragment) (trembl)",
"taxa": [
"NCBITaxon:9606"
],
"type": "biolink:Protein"
},
{
"identifier": "UniProtKB:Q4G0X0",
"label": "Q4G0X0_HUMAN DMD protein (trembl)",
"taxa": [
"NCBITaxon:9606"
],
"type": "biolink:Protein"
},
{
"identifier": "ENSEMBL:ENSP00000288447",
"type": "biolink:Protein"
},
{
"identifier": "ENSEMBL:ENSP00000288447.4",
"type": "biolink:Protein"
}
],
"descriptions": [
"dystrophin",
"A dystrophin that is encoded in the genome of human."
],
"taxa": [
"NCBITaxon:9606"
],
"clique_leaders": [
{
"identifier": "NCBIGene:1756",
"conflation": "GeneProtein",
"label": "DMD",
"description": [
"dystrophin"
],
"taxa": [
"NCBITaxon:9606"
],
"type": "biolink:Gene"
},
{
"identifier": "UniProtKB:A0A087WV90",
"conflation": "GeneProtein",
"label": "A0A087WV90_HUMAN Dystrophin (trembl)",
"taxa": [
"NCBITaxon:9606"
],
"type": "biolink:Protein"
},
{
"identifier": "UniProtKB:A0A0S2Z3B5",
"conflation": "GeneProtein",
"label": "A0A0S2Z3B5_HUMAN Dystrophin isoform 2 (trembl)",
"taxa": [
"NCBITaxon:9606"
],
"type": "biolink:Protein"
},
{
"identifier": "UniProtKB:A0A0S2Z3J7",
"conflation": "GeneProtein",
"label": "A0A0S2Z3J7_HUMAN Dystrophin isoform 1 (Fragment) (trembl)",
"taxa": [
"NCBITaxon:9606"
],
"type": "biolink:Protein"
},
{
"identifier": "UniProtKB:A0A5H1ZRP9",
"conflation": "GeneProtein",
"label": "A0A5H1ZRP9_HUMAN Dystrophin (trembl)",
"taxa": [
"NCBITaxon:9606"
],
"type": "biolink:Protein"
},
{
"identifier": "UniProtKB:A0A5H1ZRQ1",
"conflation": "GeneProtein",
"label": "A0A5H1ZRQ1_HUMAN Dystrophin (trembl)",
"taxa": [
"NCBITaxon:9606"
],
"type": "biolink:Protein"
},
{
"identifier": "UniProtKB:A0A5H1ZRQ8",
"conflation": "GeneProtein",
"label": "A0A5H1ZRQ8_HUMAN Dystrophin (trembl)",
"taxa": [
"NCBITaxon:9606"
],
"type": "biolink:Protein"
},
{
"identifier": "UniProtKB:A0A5H1ZRR9",
"conflation": "GeneProtein",
"label": "A0A5H1ZRR9_HUMAN Dystrophin (trembl)",
"taxa": [
"NCBITaxon:9606"
],
"type": "biolink:Protein"
},
{
"identifier": "UniProtKB:A0A804HKY9",
"conflation": "GeneProtein",
"label": "A0A804HKY9_HUMAN Dystrophin (trembl)",
"taxa": [
"NCBITaxon:9606"
],
"type": "biolink:Protein"
},
{
"identifier": "UniProtKB:A7E212",
"conflation": "GeneProtein",
"label": "A7E212_HUMAN Dystrophin (trembl)",
"taxa": [
"NCBITaxon:9606"
],
"type": "biolink:Protein"
},
{
"identifier": "UniProtKB:P11532",
"conflation": "GeneProtein",
"label": "DMD_HUMAN Dystrophin (sprot)",
"taxa": [
"NCBITaxon:9606"
],
"type": "biolink:Protein"
},
{
"identifier": "UniProtKB:Q16484",
"conflation": "GeneProtein",
"label": "Q16484_HUMAN DMD protein (Fragment) (trembl)",
"taxa": [
"NCBITaxon:9606"
],
"type": "biolink:Protein"
},
{
"identifier": "UniProtKB:Q4G0X0",
"conflation": "GeneProtein",
"label": "Q4G0X0_HUMAN DMD protein (trembl)",
"taxa": [
"NCBITaxon:9606"
],
"type": "biolink:Protein"
}
],
"type": [
"biolink:Gene",
"biolink:GeneOrGeneProduct",
"biolink:GenomicEntity",
"biolink:ChemicalEntityOrGeneOrGeneProduct",
"biolink:PhysicalEssence",
"biolink:OntologyClass",
"biolink:BiologicalEntity",
"biolink:ThingWithTaxon",
"biolink:NamedThing",
"biolink:PhysicalEssenceOrOccurrent",
"biolink:MacromolecularMachineMixin",
"biolink:Protein",
"biolink:GeneProductMixin",
"biolink:Polypeptide",
"biolink:ChemicalEntityOrProteinOrPolypeptide"
],
"information_content": 79.9
}
}

@gauravgaurav moved this from Backlog to In progress in Babel sprintsFeb 18, 2026
@gaurav
gaurav changed the base branch from master to add-nodenorm-version-to-statusFebruary 20, 2026 00:24
Base automatically changed from add-nodenorm-version-to-status to masterFebruary 20, 2026 00:31
@gaurav
gaurav marked this pull request as ready for review February 25, 2026 01:39
@gaurav
gaurav requested a review from CopilotFebruary 25, 2026 01:40

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This PR adds a new include_clique_leaders parameter to the /get_normalized_nodes endpoints (both GET and POST) to support deconflation use cases. When enabled, the API returns detailed information about individual clique leaders for conflated identifiers, helping users understand which cliques are being combined during gene/protein and drug/chemical conflation.

Changes:

  • Added include_clique_leaders boolean parameter to normalization endpoints
  • Modified normalization logic to collect and output clique leader information when requested
  • Updated several variable names for clarity (e.g., typestypes_with_ancestors)
  • Added LLM-generated docstrings to the get_eqids_and_types function

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 4 comments.

FileDescription
node_normalizer/server.pyAdded include_clique_leaders query parameter to GET endpoint and passed it through to normalization logic
node_normalizer/model/input.pyAdded include_clique_leaders field to CurieList input model for POST endpoint
node_normalizer/set_id.pyUpdated call to get_normalized_nodes() to explicitly pass include_clique_leaders=False
node_normalizer/normalizer.pyCore implementation: collects clique leaders when conflation is enabled, generates clique leader output with metadata (identifier, conflation type, label, description, taxa, type), and includes it in response
Comments suppressed due to low confidence (1)

node_normalizer/normalizer.py:558

  • The docstring for this function is incomplete and doesn't describe the parameters, including the new include_clique_leaders parameter. Given that the codebase uses docstring conventions (as seen in get_eqids_and_types and other functions), this function's docstring should be updated to document all parameters and their purposes, particularly the new optional parameters that control output formatting.
 """
Get value(s) for key(s) using redis MGET
"""

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment threadnode_normalizer/normalizer.py Outdated
Comment threadnode_normalizer/normalizer.py
Comment threadnode_normalizer/normalizer.py Outdated
Comment on lines +862 to +881
if clique_leaders:
for conflation_type in clique_leaders:
if canonical_id in clique_leaders[conflation_type] and eqid["i"] in clique_leaders[conflation_type][canonical_id]:
clique_leader_output = {
"identifier": eqid["i"],
"conflation": conflation_type,
}
if "label" in eq_item:
clique_leader_output["label"] = eq_item["label"]

# For description, taxa and type, we could read them from eq_item, but that
# is only set if the appropriate flag was turned on. For completeness, let's
# try picking them up if they've been passed to us at all.
if "d" in eqid and len(eqid["d"]) > 0:
clique_leader_output["description"] = eqid["d"]
if "t" in eqid and eqid["t"]:
clique_leader_output["taxa"] = eqid["t"]
if 'types' in eqid:
clique_leader_output["type"] = eqid['types'][-1]
clique_leaders_output.append(clique_leader_output)

CopilotAIFeb 25, 2026

Copy link

Choose a reason for hiding this comment

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

The loop structure here could be optimized. Currently, for every equivalent identifier, the code checks all conflation types to see if it's a clique leader. This could be improved by pre-computing a set of clique leaders for faster lookup, especially since the print statement on line 861 will execute for every single equivalent identifier in the response, which could be hundreds or thousands of times for large queries. Consider moving the clique leader check logic outside the main loop or optimizing it with a set-based lookup.

Copilot uses AI. Check for mistakes.
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
@gaurav
gaurav marked this pull request as draft February 25, 2026 01:48
@gauravgaurav mentioned this pull request Feb 25, 2026
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: In progress
Status: Backlog

Development

Successfully merging this pull request may close these issues.

Deconflation endpoint Add option to provide clique leaders in addition to the combined clique

2 participants

@gaurav
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

Add clique leaders option - #350

Draft
gaurav wants to merge 37 commits into
mainfrom
add-clique-leaders-option
Draft

Add clique leaders option#350
gaurav wants to merge 37 commits into
mainfrom
add-clique-leaders-option

Conversation

@gaurav

@gauravgaurav commented Dec 15, 2025

Copy link
Copy Markdown
Collaborator

This PR closes#320 by adding an include_clique_leaders option on normalization. This may be a way to fix#340. Also renames some variables and adds some LLM-generated function documentation.

This PR adds a new flag include_clique_leaders that can be set on both GET and POST /get_normalized_nodes endpoints. Activating this endpoint adds a clique_leaders key to each normalized identifier that includes a list of all the clique leaders in this clique, along with their name, type and taxa, and (if the appropriate flags are turned on) descriptions. This doesn't currently include all the identifiers in each clique, but that should be added without too much extra bother.

WIP

  • Would it be useful to include the list of identifiers for each clique leader? That will require some additional finagling with the code, but it shouldn't be too problematic.
  • Is clique_leaders really the best thing to call this thing? These are all clique leader identifiers, but maybe conflation_leaders or something else would be better?
  • Add tests to Babel Validator

Example

Example output for NCBIGene:1756 is included below. Note that the conflation type is included (e.g. "conflation": "GeneProtein") and that clique_leaders is a list of the cliques leaders ordered in their position in the normalization.

{
"NCBIGene:1756": {
"id": {
"identifier": "NCBIGene:1756",
"label": "DMD",
"description": "dystrophin"
},
"equivalent_identifiers": [
{
"identifier": "NCBIGene:1756",
"label": "DMD",
"description": "dystrophin",
"taxa": [
"NCBITaxon:9606"
],
"type": "biolink:Gene"
},
{
"identifier": "ENSEMBL:ENSG00000198947",
"type": "biolink:Gene"
},
{
"identifier": "HGNC:2928",
"label": "DMD",
"type": "biolink:Gene"
},
{
"identifier": "OMIM:300377",
"type": "biolink:Gene"
},
{
"identifier": "UMLS:C1414083",
"label": "DMD gene",
"type": "biolink:Gene"
},
{
"identifier": "UniProtKB:A0A087WV90",
"label": "A0A087WV90_HUMAN Dystrophin (trembl)",
"taxa": [
"NCBITaxon:9606"
],
"type": "biolink:Protein"
},
{
"identifier": "UniProtKB:A0A0S2Z3B5",
"label": "A0A0S2Z3B5_HUMAN Dystrophin isoform 2 (trembl)",
"taxa": [
"NCBITaxon:9606"
],
"type": "biolink:Protein"
},
{
"identifier": "UniProtKB:A0A0S2Z3J7",
"label": "A0A0S2Z3J7_HUMAN Dystrophin isoform 1 (Fragment) (trembl)",
"taxa": [
"NCBITaxon:9606"
],
"type": "biolink:Protein"
},
{
"identifier": "UniProtKB:A0A5H1ZRP9",
"label": "A0A5H1ZRP9_HUMAN Dystrophin (trembl)",
"taxa": [
"NCBITaxon:9606"
],
"type": "biolink:Protein"
},
{
"identifier": "UniProtKB:A0A5H1ZRQ1",
"label": "A0A5H1ZRQ1_HUMAN Dystrophin (trembl)",
"taxa": [
"NCBITaxon:9606"
],
"type": "biolink:Protein"
},
{
"identifier": "UniProtKB:A0A5H1ZRQ8",
"label": "A0A5H1ZRQ8_HUMAN Dystrophin (trembl)",
"taxa": [
"NCBITaxon:9606"
],
"type": "biolink:Protein"
},
{
"identifier": "UniProtKB:A0A5H1ZRR9",
"label": "A0A5H1ZRR9_HUMAN Dystrophin (trembl)",
"taxa": [
"NCBITaxon:9606"
],
"type": "biolink:Protein"
},
{
"identifier": "UniProtKB:A0A804HKY9",
"label": "A0A804HKY9_HUMAN Dystrophin (trembl)",
"taxa": [
"NCBITaxon:9606"
],
"type": "biolink:Protein"
},
{
"identifier": "UniProtKB:A7E212",
"label": "A7E212_HUMAN Dystrophin (trembl)",
"taxa": [
"NCBITaxon:9606"
],
"type": "biolink:Protein"
},
{
"identifier": "UniProtKB:P11532",
"label": "DMD_HUMAN Dystrophin (sprot)",
"taxa": [
"NCBITaxon:9606"
],
"type": "biolink:Protein"
},
{
"identifier": "PR:P11532",
"label": "dystrophin (human)",
"description": "A dystrophin that is encoded in the genome of human.",
"type": "biolink:Protein"
},
{
"identifier": "UMLS:C1437024",
"label": "DMD protein, human",
"type": "biolink:Protein"
},
{
"identifier": "MESH:C484258",
"label": "DMD protein, human",
"type": "biolink:Protein"
},
{
"identifier": "UniProtKB:Q16484",
"label": "Q16484_HUMAN DMD protein (Fragment) (trembl)",
"taxa": [
"NCBITaxon:9606"
],
"type": "biolink:Protein"
},
{
"identifier": "UniProtKB:Q4G0X0",
"label": "Q4G0X0_HUMAN DMD protein (trembl)",
"taxa": [
"NCBITaxon:9606"
],
"type": "biolink:Protein"
},
{
"identifier": "ENSEMBL:ENSP00000288447",
"type": "biolink:Protein"
},
{
"identifier": "ENSEMBL:ENSP00000288447.4",
"type": "biolink:Protein"
}
],
"descriptions": [
"dystrophin",
"A dystrophin that is encoded in the genome of human."
],
"taxa": [
"NCBITaxon:9606"
],
"clique_leaders": [
{
"identifier": "NCBIGene:1756",
"conflation": "GeneProtein",
"label": "DMD",
"description": [
"dystrophin"
],
"taxa": [
"NCBITaxon:9606"
],
"type": "biolink:Gene"
},
{
"identifier": "UniProtKB:A0A087WV90",
"conflation": "GeneProtein",
"label": "A0A087WV90_HUMAN Dystrophin (trembl)",
"taxa": [
"NCBITaxon:9606"
],
"type": "biolink:Protein"
},
{
"identifier": "UniProtKB:A0A0S2Z3B5",
"conflation": "GeneProtein",
"label": "A0A0S2Z3B5_HUMAN Dystrophin isoform 2 (trembl)",
"taxa": [
"NCBITaxon:9606"
],
"type": "biolink:Protein"
},
{
"identifier": "UniProtKB:A0A0S2Z3J7",
"conflation": "GeneProtein",
"label": "A0A0S2Z3J7_HUMAN Dystrophin isoform 1 (Fragment) (trembl)",
"taxa": [
"NCBITaxon:9606"
],
"type": "biolink:Protein"
},
{
"identifier": "UniProtKB:A0A5H1ZRP9",
"conflation": "GeneProtein",
"label": "A0A5H1ZRP9_HUMAN Dystrophin (trembl)",
"taxa": [
"NCBITaxon:9606"
],
"type": "biolink:Protein"
},
{
"identifier": "UniProtKB:A0A5H1ZRQ1",
"conflation": "GeneProtein",
"label": "A0A5H1ZRQ1_HUMAN Dystrophin (trembl)",
"taxa": [
"NCBITaxon:9606"
],
"type": "biolink:Protein"
},
{
"identifier": "UniProtKB:A0A5H1ZRQ8",
"conflation": "GeneProtein",
"label": "A0A5H1ZRQ8_HUMAN Dystrophin (trembl)",
"taxa": [
"NCBITaxon:9606"
],
"type": "biolink:Protein"
},
{
"identifier": "UniProtKB:A0A5H1ZRR9",
"conflation": "GeneProtein",
"label": "A0A5H1ZRR9_HUMAN Dystrophin (trembl)",
"taxa": [
"NCBITaxon:9606"
],
"type": "biolink:Protein"
},
{
"identifier": "UniProtKB:A0A804HKY9",
"conflation": "GeneProtein",
"label": "A0A804HKY9_HUMAN Dystrophin (trembl)",
"taxa": [
"NCBITaxon:9606"
],
"type": "biolink:Protein"
},
{
"identifier": "UniProtKB:A7E212",
"conflation": "GeneProtein",
"label": "A7E212_HUMAN Dystrophin (trembl)",
"taxa": [
"NCBITaxon:9606"
],
"type": "biolink:Protein"
},
{
"identifier": "UniProtKB:P11532",
"conflation": "GeneProtein",
"label": "DMD_HUMAN Dystrophin (sprot)",
"taxa": [
"NCBITaxon:9606"
],
"type": "biolink:Protein"
},
{
"identifier": "UniProtKB:Q16484",
"conflation": "GeneProtein",
"label": "Q16484_HUMAN DMD protein (Fragment) (trembl)",
"taxa": [
"NCBITaxon:9606"
],
"type": "biolink:Protein"
},
{
"identifier": "UniProtKB:Q4G0X0",
"conflation": "GeneProtein",
"label": "Q4G0X0_HUMAN DMD protein (trembl)",
"taxa": [
"NCBITaxon:9606"
],
"type": "biolink:Protein"
}
],
"type": [
"biolink:Gene",
"biolink:GeneOrGeneProduct",
"biolink:GenomicEntity",
"biolink:ChemicalEntityOrGeneOrGeneProduct",
"biolink:PhysicalEssence",
"biolink:OntologyClass",
"biolink:BiologicalEntity",
"biolink:ThingWithTaxon",
"biolink:NamedThing",
"biolink:PhysicalEssenceOrOccurrent",
"biolink:MacromolecularMachineMixin",
"biolink:Protein",
"biolink:GeneProductMixin",
"biolink:Polypeptide",
"biolink:ChemicalEntityOrProteinOrPolypeptide"
],
"information_content": 79.9
}
}

@gauravgaurav moved this from Backlog to In progress in Babel sprintsFeb 18, 2026
@gaurav
gaurav changed the base branch from master to add-nodenorm-version-to-statusFebruary 20, 2026 00:24
Base automatically changed from add-nodenorm-version-to-status to masterFebruary 20, 2026 00:31
@gaurav
gaurav marked this pull request as ready for review February 25, 2026 01:39
@gaurav
gaurav requested a review from CopilotFebruary 25, 2026 01:40

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This PR adds a new include_clique_leaders parameter to the /get_normalized_nodes endpoints (both GET and POST) to support deconflation use cases. When enabled, the API returns detailed information about individual clique leaders for conflated identifiers, helping users understand which cliques are being combined during gene/protein and drug/chemical conflation.

Changes:

  • Added include_clique_leaders boolean parameter to normalization endpoints
  • Modified normalization logic to collect and output clique leader information when requested
  • Updated several variable names for clarity (e.g., typestypes_with_ancestors)
  • Added LLM-generated docstrings to the get_eqids_and_types function

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 4 comments.

FileDescription
node_normalizer/server.pyAdded include_clique_leaders query parameter to GET endpoint and passed it through to normalization logic
node_normalizer/model/input.pyAdded include_clique_leaders field to CurieList input model for POST endpoint
node_normalizer/set_id.pyUpdated call to get_normalized_nodes() to explicitly pass include_clique_leaders=False
node_normalizer/normalizer.pyCore implementation: collects clique leaders when conflation is enabled, generates clique leader output with metadata (identifier, conflation type, label, description, taxa, type), and includes it in response
Comments suppressed due to low confidence (1)

node_normalizer/normalizer.py:558

  • The docstring for this function is incomplete and doesn't describe the parameters, including the new include_clique_leaders parameter. Given that the codebase uses docstring conventions (as seen in get_eqids_and_types and other functions), this function's docstring should be updated to document all parameters and their purposes, particularly the new optional parameters that control output formatting.
 """
Get value(s) for key(s) using redis MGET
"""

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment threadnode_normalizer/normalizer.py Outdated
Comment threadnode_normalizer/normalizer.py
Comment threadnode_normalizer/normalizer.py Outdated
Comment on lines +862 to +881
if clique_leaders:
for conflation_type in clique_leaders:
if canonical_id in clique_leaders[conflation_type] and eqid["i"] in clique_leaders[conflation_type][canonical_id]:
clique_leader_output = {
"identifier": eqid["i"],
"conflation": conflation_type,
}
if "label" in eq_item:
clique_leader_output["label"] = eq_item["label"]

# For description, taxa and type, we could read them from eq_item, but that
# is only set if the appropriate flag was turned on. For completeness, let's
# try picking them up if they've been passed to us at all.
if "d" in eqid and len(eqid["d"]) > 0:
clique_leader_output["description"] = eqid["d"]
if "t" in eqid and eqid["t"]:
clique_leader_output["taxa"] = eqid["t"]
if 'types' in eqid:
clique_leader_output["type"] = eqid['types'][-1]
clique_leaders_output.append(clique_leader_output)

CopilotAIFeb 25, 2026

Copy link

Choose a reason for hiding this comment

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

The loop structure here could be optimized. Currently, for every equivalent identifier, the code checks all conflation types to see if it's a clique leader. This could be improved by pre-computing a set of clique leaders for faster lookup, especially since the print statement on line 861 will execute for every single equivalent identifier in the response, which could be hundreds or thousands of times for large queries. Consider moving the clique leader check logic outside the main loop or optimizing it with a set-based lookup.

Copilot uses AI. Check for mistakes.
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
@gaurav
gaurav marked this pull request as draft February 25, 2026 01:48
@gauravgaurav mentioned this pull request Feb 25, 2026
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: In progress
Status: Backlog

Development

Successfully merging this pull request may close these issues.

Deconflation endpoint Add option to provide clique leaders in addition to the combined clique

2 participants

@gaurav
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Add clique leaders option - #350

Draft
gaurav wants to merge 37 commits into
mainfrom
add-clique-leaders-option
Draft

Add clique leaders option#350
gaurav wants to merge 37 commits into
mainfrom
add-clique-leaders-option

Conversation

@gaurav

@gauravgaurav commented Dec 15, 2025

Copy link
Copy Markdown
Collaborator

This PR closes#320 by adding an include_clique_leaders option on normalization. This may be a way to fix#340. Also renames some variables and adds some LLM-generated function documentation.

This PR adds a new flag include_clique_leaders that can be set on both GET and POST /get_normalized_nodes endpoints. Activating this endpoint adds a clique_leaders key to each normalized identifier that includes a list of all the clique leaders in this clique, along with their name, type and taxa, and (if the appropriate flags are turned on) descriptions. This doesn't currently include all the identifiers in each clique, but that should be added without too much extra bother.

WIP

  • Would it be useful to include the list of identifiers for each clique leader? That will require some additional finagling with the code, but it shouldn't be too problematic.
  • Is clique_leaders really the best thing to call this thing? These are all clique leader identifiers, but maybe conflation_leaders or something else would be better?
  • Add tests to Babel Validator

Example

Example output for NCBIGene:1756 is included below. Note that the conflation type is included (e.g. "conflation": "GeneProtein") and that clique_leaders is a list of the cliques leaders ordered in their position in the normalization.

{
"NCBIGene:1756": {
"id": {
"identifier": "NCBIGene:1756",
"label": "DMD",
"description": "dystrophin"
},
"equivalent_identifiers": [
{
"identifier": "NCBIGene:1756",
"label": "DMD",
"description": "dystrophin",
"taxa": [
"NCBITaxon:9606"
],
"type": "biolink:Gene"
},
{
"identifier": "ENSEMBL:ENSG00000198947",
"type": "biolink:Gene"
},
{
"identifier": "HGNC:2928",
"label": "DMD",
"type": "biolink:Gene"
},
{
"identifier": "OMIM:300377",
"type": "biolink:Gene"
},
{
"identifier": "UMLS:C1414083",
"label": "DMD gene",
"type": "biolink:Gene"
},
{
"identifier": "UniProtKB:A0A087WV90",
"label": "A0A087WV90_HUMAN Dystrophin (trembl)",
"taxa": [
"NCBITaxon:9606"
],
"type": "biolink:Protein"
},
{
"identifier": "UniProtKB:A0A0S2Z3B5",
"label": "A0A0S2Z3B5_HUMAN Dystrophin isoform 2 (trembl)",
"taxa": [
"NCBITaxon:9606"
],
"type": "biolink:Protein"
},
{
"identifier": "UniProtKB:A0A0S2Z3J7",
"label": "A0A0S2Z3J7_HUMAN Dystrophin isoform 1 (Fragment) (trembl)",
"taxa": [
"NCBITaxon:9606"
],
"type": "biolink:Protein"
},
{
"identifier": "UniProtKB:A0A5H1ZRP9",
"label": "A0A5H1ZRP9_HUMAN Dystrophin (trembl)",
"taxa": [
"NCBITaxon:9606"
],
"type": "biolink:Protein"
},
{
"identifier": "UniProtKB:A0A5H1ZRQ1",
"label": "A0A5H1ZRQ1_HUMAN Dystrophin (trembl)",
"taxa": [
"NCBITaxon:9606"
],
"type": "biolink:Protein"
},
{
"identifier": "UniProtKB:A0A5H1ZRQ8",
"label": "A0A5H1ZRQ8_HUMAN Dystrophin (trembl)",
"taxa": [
"NCBITaxon:9606"
],
"type": "biolink:Protein"
},
{
"identifier": "UniProtKB:A0A5H1ZRR9",
"label": "A0A5H1ZRR9_HUMAN Dystrophin (trembl)",
"taxa": [
"NCBITaxon:9606"
],
"type": "biolink:Protein"
},
{
"identifier": "UniProtKB:A0A804HKY9",
"label": "A0A804HKY9_HUMAN Dystrophin (trembl)",
"taxa": [
"NCBITaxon:9606"
],
"type": "biolink:Protein"
},
{
"identifier": "UniProtKB:A7E212",
"label": "A7E212_HUMAN Dystrophin (trembl)",
"taxa": [
"NCBITaxon:9606"
],
"type": "biolink:Protein"
},
{
"identifier": "UniProtKB:P11532",
"label": "DMD_HUMAN Dystrophin (sprot)",
"taxa": [
"NCBITaxon:9606"
],
"type": "biolink:Protein"
},
{
"identifier": "PR:P11532",
"label": "dystrophin (human)",
"description": "A dystrophin that is encoded in the genome of human.",
"type": "biolink:Protein"
},
{
"identifier": "UMLS:C1437024",
"label": "DMD protein, human",
"type": "biolink:Protein"
},
{
"identifier": "MESH:C484258",
"label": "DMD protein, human",
"type": "biolink:Protein"
},
{
"identifier": "UniProtKB:Q16484",
"label": "Q16484_HUMAN DMD protein (Fragment) (trembl)",
"taxa": [
"NCBITaxon:9606"
],
"type": "biolink:Protein"
},
{
"identifier": "UniProtKB:Q4G0X0",
"label": "Q4G0X0_HUMAN DMD protein (trembl)",
"taxa": [
"NCBITaxon:9606"
],
"type": "biolink:Protein"
},
{
"identifier": "ENSEMBL:ENSP00000288447",
"type": "biolink:Protein"
},
{
"identifier": "ENSEMBL:ENSP00000288447.4",
"type": "biolink:Protein"
}
],
"descriptions": [
"dystrophin",
"A dystrophin that is encoded in the genome of human."
],
"taxa": [
"NCBITaxon:9606"
],
"clique_leaders": [
{
"identifier": "NCBIGene:1756",
"conflation": "GeneProtein",
"label": "DMD",
"description": [
"dystrophin"
],
"taxa": [
"NCBITaxon:9606"
],
"type": "biolink:Gene"
},
{
"identifier": "UniProtKB:A0A087WV90",
"conflation": "GeneProtein",
"label": "A0A087WV90_HUMAN Dystrophin (trembl)",
"taxa": [
"NCBITaxon:9606"
],
"type": "biolink:Protein"
},
{
"identifier": "UniProtKB:A0A0S2Z3B5",
"conflation": "GeneProtein",
"label": "A0A0S2Z3B5_HUMAN Dystrophin isoform 2 (trembl)",
"taxa": [
"NCBITaxon:9606"
],
"type": "biolink:Protein"
},
{
"identifier": "UniProtKB:A0A0S2Z3J7",
"conflation": "GeneProtein",
"label": "A0A0S2Z3J7_HUMAN Dystrophin isoform 1 (Fragment) (trembl)",
"taxa": [
"NCBITaxon:9606"
],
"type": "biolink:Protein"
},
{
"identifier": "UniProtKB:A0A5H1ZRP9",
"conflation": "GeneProtein",
"label": "A0A5H1ZRP9_HUMAN Dystrophin (trembl)",
"taxa": [
"NCBITaxon:9606"
],
"type": "biolink:Protein"
},
{
"identifier": "UniProtKB:A0A5H1ZRQ1",
"conflation": "GeneProtein",
"label": "A0A5H1ZRQ1_HUMAN Dystrophin (trembl)",
"taxa": [
"NCBITaxon:9606"
],
"type": "biolink:Protein"
},
{
"identifier": "UniProtKB:A0A5H1ZRQ8",
"conflation": "GeneProtein",
"label": "A0A5H1ZRQ8_HUMAN Dystrophin (trembl)",
"taxa": [
"NCBITaxon:9606"
],
"type": "biolink:Protein"
},
{
"identifier": "UniProtKB:A0A5H1ZRR9",
"conflation": "GeneProtein",
"label": "A0A5H1ZRR9_HUMAN Dystrophin (trembl)",
"taxa": [
"NCBITaxon:9606"
],
"type": "biolink:Protein"
},
{
"identifier": "UniProtKB:A0A804HKY9",
"conflation": "GeneProtein",
"label": "A0A804HKY9_HUMAN Dystrophin (trembl)",
"taxa": [
"NCBITaxon:9606"
],
"type": "biolink:Protein"
},
{
"identifier": "UniProtKB:A7E212",
"conflation": "GeneProtein",
"label": "A7E212_HUMAN Dystrophin (trembl)",
"taxa": [
"NCBITaxon:9606"
],
"type": "biolink:Protein"
},
{
"identifier": "UniProtKB:P11532",
"conflation": "GeneProtein",
"label": "DMD_HUMAN Dystrophin (sprot)",
"taxa": [
"NCBITaxon:9606"
],
"type": "biolink:Protein"
},
{
"identifier": "UniProtKB:Q16484",
"conflation": "GeneProtein",
"label": "Q16484_HUMAN DMD protein (Fragment) (trembl)",
"taxa": [
"NCBITaxon:9606"
],
"type": "biolink:Protein"
},
{
"identifier": "UniProtKB:Q4G0X0",
"conflation": "GeneProtein",
"label": "Q4G0X0_HUMAN DMD protein (trembl)",
"taxa": [
"NCBITaxon:9606"
],
"type": "biolink:Protein"
}
],
"type": [
"biolink:Gene",
"biolink:GeneOrGeneProduct",
"biolink:GenomicEntity",
"biolink:ChemicalEntityOrGeneOrGeneProduct",
"biolink:PhysicalEssence",
"biolink:OntologyClass",
"biolink:BiologicalEntity",
"biolink:ThingWithTaxon",
"biolink:NamedThing",
"biolink:PhysicalEssenceOrOccurrent",
"biolink:MacromolecularMachineMixin",
"biolink:Protein",
"biolink:GeneProductMixin",
"biolink:Polypeptide",
"biolink:ChemicalEntityOrProteinOrPolypeptide"
],
"information_content": 79.9
}
}

@gauravgaurav moved this from Backlog to In progress in Babel sprintsFeb 18, 2026
@gaurav
gaurav changed the base branch from master to add-nodenorm-version-to-statusFebruary 20, 2026 00:24
Base automatically changed from add-nodenorm-version-to-status to masterFebruary 20, 2026 00:31
@gaurav
gaurav marked this pull request as ready for review February 25, 2026 01:39
@gaurav
gaurav requested a review from CopilotFebruary 25, 2026 01:40

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This PR adds a new include_clique_leaders parameter to the /get_normalized_nodes endpoints (both GET and POST) to support deconflation use cases. When enabled, the API returns detailed information about individual clique leaders for conflated identifiers, helping users understand which cliques are being combined during gene/protein and drug/chemical conflation.

Changes:

  • Added include_clique_leaders boolean parameter to normalization endpoints
  • Modified normalization logic to collect and output clique leader information when requested
  • Updated several variable names for clarity (e.g., typestypes_with_ancestors)
  • Added LLM-generated docstrings to the get_eqids_and_types function

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 4 comments.

FileDescription
node_normalizer/server.pyAdded include_clique_leaders query parameter to GET endpoint and passed it through to normalization logic
node_normalizer/model/input.pyAdded include_clique_leaders field to CurieList input model for POST endpoint
node_normalizer/set_id.pyUpdated call to get_normalized_nodes() to explicitly pass include_clique_leaders=False
node_normalizer/normalizer.pyCore implementation: collects clique leaders when conflation is enabled, generates clique leader output with metadata (identifier, conflation type, label, description, taxa, type), and includes it in response
Comments suppressed due to low confidence (1)

node_normalizer/normalizer.py:558

  • The docstring for this function is incomplete and doesn't describe the parameters, including the new include_clique_leaders parameter. Given that the codebase uses docstring conventions (as seen in get_eqids_and_types and other functions), this function's docstring should be updated to document all parameters and their purposes, particularly the new optional parameters that control output formatting.
 """
Get value(s) for key(s) using redis MGET
"""

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment threadnode_normalizer/normalizer.py Outdated
Comment threadnode_normalizer/normalizer.py
Comment threadnode_normalizer/normalizer.py Outdated
Comment on lines +862 to +881
if clique_leaders:
for conflation_type in clique_leaders:
if canonical_id in clique_leaders[conflation_type] and eqid["i"] in clique_leaders[conflation_type][canonical_id]:
clique_leader_output = {
"identifier": eqid["i"],
"conflation": conflation_type,
}
if "label" in eq_item:
clique_leader_output["label"] = eq_item["label"]

# For description, taxa and type, we could read them from eq_item, but that
# is only set if the appropriate flag was turned on. For completeness, let's
# try picking them up if they've been passed to us at all.
if "d" in eqid and len(eqid["d"]) > 0:
clique_leader_output["description"] = eqid["d"]
if "t" in eqid and eqid["t"]:
clique_leader_output["taxa"] = eqid["t"]
if 'types' in eqid:
clique_leader_output["type"] = eqid['types'][-1]
clique_leaders_output.append(clique_leader_output)

CopilotAIFeb 25, 2026

Copy link

Choose a reason for hiding this comment

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

The loop structure here could be optimized. Currently, for every equivalent identifier, the code checks all conflation types to see if it's a clique leader. This could be improved by pre-computing a set of clique leaders for faster lookup, especially since the print statement on line 861 will execute for every single equivalent identifier in the response, which could be hundreds or thousands of times for large queries. Consider moving the clique leader check logic outside the main loop or optimizing it with a set-based lookup.

Copilot uses AI. Check for mistakes.
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
@gaurav
gaurav marked this pull request as draft February 25, 2026 01:48
@gauravgaurav mentioned this pull request Feb 25, 2026
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: In progress
Status: Backlog

Development

Successfully merging this pull request may close these issues.

Deconflation endpoint Add option to provide clique leaders in addition to the combined clique

2 participants

@gaurav
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Add clique leaders option - #350

Draft
gaurav wants to merge 37 commits into
mainfrom
add-clique-leaders-option
Draft

Add clique leaders option#350
gaurav wants to merge 37 commits into
mainfrom
add-clique-leaders-option

Conversation

@gaurav

@gauravgaurav commented Dec 15, 2025

Copy link
Copy Markdown
Collaborator

This PR closes#320 by adding an include_clique_leaders option on normalization. This may be a way to fix#340. Also renames some variables and adds some LLM-generated function documentation.

This PR adds a new flag include_clique_leaders that can be set on both GET and POST /get_normalized_nodes endpoints. Activating this endpoint adds a clique_leaders key to each normalized identifier that includes a list of all the clique leaders in this clique, along with their name, type and taxa, and (if the appropriate flags are turned on) descriptions. This doesn't currently include all the identifiers in each clique, but that should be added without too much extra bother.

WIP

  • Would it be useful to include the list of identifiers for each clique leader? That will require some additional finagling with the code, but it shouldn't be too problematic.
  • Is clique_leaders really the best thing to call this thing? These are all clique leader identifiers, but maybe conflation_leaders or something else would be better?
  • Add tests to Babel Validator

Example

Example output for NCBIGene:1756 is included below. Note that the conflation type is included (e.g. "conflation": "GeneProtein") and that clique_leaders is a list of the cliques leaders ordered in their position in the normalization.

{
"NCBIGene:1756": {
"id": {
"identifier": "NCBIGene:1756",
"label": "DMD",
"description": "dystrophin"
},
"equivalent_identifiers": [
{
"identifier": "NCBIGene:1756",
"label": "DMD",
"description": "dystrophin",
"taxa": [
"NCBITaxon:9606"
],
"type": "biolink:Gene"
},
{
"identifier": "ENSEMBL:ENSG00000198947",
"type": "biolink:Gene"
},
{
"identifier": "HGNC:2928",
"label": "DMD",
"type": "biolink:Gene"
},
{
"identifier": "OMIM:300377",
"type": "biolink:Gene"
},
{
"identifier": "UMLS:C1414083",
"label": "DMD gene",
"type": "biolink:Gene"
},
{
"identifier": "UniProtKB:A0A087WV90",
"label": "A0A087WV90_HUMAN Dystrophin (trembl)",
"taxa": [
"NCBITaxon:9606"
],
"type": "biolink:Protein"
},
{
"identifier": "UniProtKB:A0A0S2Z3B5",
"label": "A0A0S2Z3B5_HUMAN Dystrophin isoform 2 (trembl)",
"taxa": [
"NCBITaxon:9606"
],
"type": "biolink:Protein"
},
{
"identifier": "UniProtKB:A0A0S2Z3J7",
"label": "A0A0S2Z3J7_HUMAN Dystrophin isoform 1 (Fragment) (trembl)",
"taxa": [
"NCBITaxon:9606"
],
"type": "biolink:Protein"
},
{
"identifier": "UniProtKB:A0A5H1ZRP9",
"label": "A0A5H1ZRP9_HUMAN Dystrophin (trembl)",
"taxa": [
"NCBITaxon:9606"
],
"type": "biolink:Protein"
},
{
"identifier": "UniProtKB:A0A5H1ZRQ1",
"label": "A0A5H1ZRQ1_HUMAN Dystrophin (trembl)",
"taxa": [
"NCBITaxon:9606"
],
"type": "biolink:Protein"
},
{
"identifier": "UniProtKB:A0A5H1ZRQ8",
"label": "A0A5H1ZRQ8_HUMAN Dystrophin (trembl)",
"taxa": [
"NCBITaxon:9606"
],
"type": "biolink:Protein"
},
{
"identifier": "UniProtKB:A0A5H1ZRR9",
"label": "A0A5H1ZRR9_HUMAN Dystrophin (trembl)",
"taxa": [
"NCBITaxon:9606"
],
"type": "biolink:Protein"
},
{
"identifier": "UniProtKB:A0A804HKY9",
"label": "A0A804HKY9_HUMAN Dystrophin (trembl)",
"taxa": [
"NCBITaxon:9606"
],
"type": "biolink:Protein"
},
{
"identifier": "UniProtKB:A7E212",
"label": "A7E212_HUMAN Dystrophin (trembl)",
"taxa": [
"NCBITaxon:9606"
],
"type": "biolink:Protein"
},
{
"identifier": "UniProtKB:P11532",
"label": "DMD_HUMAN Dystrophin (sprot)",
"taxa": [
"NCBITaxon:9606"
],
"type": "biolink:Protein"
},
{
"identifier": "PR:P11532",
"label": "dystrophin (human)",
"description": "A dystrophin that is encoded in the genome of human.",
"type": "biolink:Protein"
},
{
"identifier": "UMLS:C1437024",
"label": "DMD protein, human",
"type": "biolink:Protein"
},
{
"identifier": "MESH:C484258",
"label": "DMD protein, human",
"type": "biolink:Protein"
},
{
"identifier": "UniProtKB:Q16484",
"label": "Q16484_HUMAN DMD protein (Fragment) (trembl)",
"taxa": [
"NCBITaxon:9606"
],
"type": "biolink:Protein"
},
{
"identifier": "UniProtKB:Q4G0X0",
"label": "Q4G0X0_HUMAN DMD protein (trembl)",
"taxa": [
"NCBITaxon:9606"
],
"type": "biolink:Protein"
},
{
"identifier": "ENSEMBL:ENSP00000288447",
"type": "biolink:Protein"
},
{
"identifier": "ENSEMBL:ENSP00000288447.4",
"type": "biolink:Protein"
}
],
"descriptions": [
"dystrophin",
"A dystrophin that is encoded in the genome of human."
],
"taxa": [
"NCBITaxon:9606"
],
"clique_leaders": [
{
"identifier": "NCBIGene:1756",
"conflation": "GeneProtein",
"label": "DMD",
"description": [
"dystrophin"
],
"taxa": [
"NCBITaxon:9606"
],
"type": "biolink:Gene"
},
{
"identifier": "UniProtKB:A0A087WV90",
"conflation": "GeneProtein",
"label": "A0A087WV90_HUMAN Dystrophin (trembl)",
"taxa": [
"NCBITaxon:9606"
],
"type": "biolink:Protein"
},
{
"identifier": "UniProtKB:A0A0S2Z3B5",
"conflation": "GeneProtein",
"label": "A0A0S2Z3B5_HUMAN Dystrophin isoform 2 (trembl)",
"taxa": [
"NCBITaxon:9606"
],
"type": "biolink:Protein"
},
{
"identifier": "UniProtKB:A0A0S2Z3J7",
"conflation": "GeneProtein",
"label": "A0A0S2Z3J7_HUMAN Dystrophin isoform 1 (Fragment) (trembl)",
"taxa": [
"NCBITaxon:9606"
],
"type": "biolink:Protein"
},
{
"identifier": "UniProtKB:A0A5H1ZRP9",
"conflation": "GeneProtein",
"label": "A0A5H1ZRP9_HUMAN Dystrophin (trembl)",
"taxa": [
"NCBITaxon:9606"
],
"type": "biolink:Protein"
},
{
"identifier": "UniProtKB:A0A5H1ZRQ1",
"conflation": "GeneProtein",
"label": "A0A5H1ZRQ1_HUMAN Dystrophin (trembl)",
"taxa": [
"NCBITaxon:9606"
],
"type": "biolink:Protein"
},
{
"identifier": "UniProtKB:A0A5H1ZRQ8",
"conflation": "GeneProtein",
"label": "A0A5H1ZRQ8_HUMAN Dystrophin (trembl)",
"taxa": [
"NCBITaxon:9606"
],
"type": "biolink:Protein"
},
{
"identifier": "UniProtKB:A0A5H1ZRR9",
"conflation": "GeneProtein",
"label": "A0A5H1ZRR9_HUMAN Dystrophin (trembl)",
"taxa": [
"NCBITaxon:9606"
],
"type": "biolink:Protein"
},
{
"identifier": "UniProtKB:A0A804HKY9",
"conflation": "GeneProtein",
"label": "A0A804HKY9_HUMAN Dystrophin (trembl)",
"taxa": [
"NCBITaxon:9606"
],
"type": "biolink:Protein"
},
{
"identifier": "UniProtKB:A7E212",
"conflation": "GeneProtein",
"label": "A7E212_HUMAN Dystrophin (trembl)",
"taxa": [
"NCBITaxon:9606"
],
"type": "biolink:Protein"
},
{
"identifier": "UniProtKB:P11532",
"conflation": "GeneProtein",
"label": "DMD_HUMAN Dystrophin (sprot)",
"taxa": [
"NCBITaxon:9606"
],
"type": "biolink:Protein"
},
{
"identifier": "UniProtKB:Q16484",
"conflation": "GeneProtein",
"label": "Q16484_HUMAN DMD protein (Fragment) (trembl)",
"taxa": [
"NCBITaxon:9606"
],
"type": "biolink:Protein"
},
{
"identifier": "UniProtKB:Q4G0X0",
"conflation": "GeneProtein",
"label": "Q4G0X0_HUMAN DMD protein (trembl)",
"taxa": [
"NCBITaxon:9606"
],
"type": "biolink:Protein"
}
],
"type": [
"biolink:Gene",
"biolink:GeneOrGeneProduct",
"biolink:GenomicEntity",
"biolink:ChemicalEntityOrGeneOrGeneProduct",
"biolink:PhysicalEssence",
"biolink:OntologyClass",
"biolink:BiologicalEntity",
"biolink:ThingWithTaxon",
"biolink:NamedThing",
"biolink:PhysicalEssenceOrOccurrent",
"biolink:MacromolecularMachineMixin",
"biolink:Protein",
"biolink:GeneProductMixin",
"biolink:Polypeptide",
"biolink:ChemicalEntityOrProteinOrPolypeptide"
],
"information_content": 79.9
}
}

@gauravgaurav moved this from Backlog to In progress in Babel sprintsFeb 18, 2026
@gaurav
gaurav changed the base branch from master to add-nodenorm-version-to-statusFebruary 20, 2026 00:24
Base automatically changed from add-nodenorm-version-to-status to masterFebruary 20, 2026 00:31
@gaurav
gaurav marked this pull request as ready for review February 25, 2026 01:39
@gaurav
gaurav requested a review from CopilotFebruary 25, 2026 01:40

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This PR adds a new include_clique_leaders parameter to the /get_normalized_nodes endpoints (both GET and POST) to support deconflation use cases. When enabled, the API returns detailed information about individual clique leaders for conflated identifiers, helping users understand which cliques are being combined during gene/protein and drug/chemical conflation.

Changes:

  • Added include_clique_leaders boolean parameter to normalization endpoints
  • Modified normalization logic to collect and output clique leader information when requested
  • Updated several variable names for clarity (e.g., typestypes_with_ancestors)
  • Added LLM-generated docstrings to the get_eqids_and_types function

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 4 comments.

FileDescription
node_normalizer/server.pyAdded include_clique_leaders query parameter to GET endpoint and passed it through to normalization logic
node_normalizer/model/input.pyAdded include_clique_leaders field to CurieList input model for POST endpoint
node_normalizer/set_id.pyUpdated call to get_normalized_nodes() to explicitly pass include_clique_leaders=False
node_normalizer/normalizer.pyCore implementation: collects clique leaders when conflation is enabled, generates clique leader output with metadata (identifier, conflation type, label, description, taxa, type), and includes it in response
Comments suppressed due to low confidence (1)

node_normalizer/normalizer.py:558

  • The docstring for this function is incomplete and doesn't describe the parameters, including the new include_clique_leaders parameter. Given that the codebase uses docstring conventions (as seen in get_eqids_and_types and other functions), this function's docstring should be updated to document all parameters and their purposes, particularly the new optional parameters that control output formatting.
 """
Get value(s) for key(s) using redis MGET
"""

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment threadnode_normalizer/normalizer.py Outdated
Comment threadnode_normalizer/normalizer.py
Comment threadnode_normalizer/normalizer.py Outdated
Comment on lines +862 to +881
if clique_leaders:
for conflation_type in clique_leaders:
if canonical_id in clique_leaders[conflation_type] and eqid["i"] in clique_leaders[conflation_type][canonical_id]:
clique_leader_output = {
"identifier": eqid["i"],
"conflation": conflation_type,
}
if "label" in eq_item:
clique_leader_output["label"] = eq_item["label"]

# For description, taxa and type, we could read them from eq_item, but that
# is only set if the appropriate flag was turned on. For completeness, let's
# try picking them up if they've been passed to us at all.
if "d" in eqid and len(eqid["d"]) > 0:
clique_leader_output["description"] = eqid["d"]
if "t" in eqid and eqid["t"]:
clique_leader_output["taxa"] = eqid["t"]
if 'types' in eqid:
clique_leader_output["type"] = eqid['types'][-1]
clique_leaders_output.append(clique_leader_output)

CopilotAIFeb 25, 2026

Copy link

Choose a reason for hiding this comment

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

The loop structure here could be optimized. Currently, for every equivalent identifier, the code checks all conflation types to see if it's a clique leader. This could be improved by pre-computing a set of clique leaders for faster lookup, especially since the print statement on line 861 will execute for every single equivalent identifier in the response, which could be hundreds or thousands of times for large queries. Consider moving the clique leader check logic outside the main loop or optimizing it with a set-based lookup.

Copilot uses AI. Check for mistakes.
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
@gaurav
gaurav marked this pull request as draft February 25, 2026 01:48
@gauravgaurav mentioned this pull request Feb 25, 2026
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: In progress
Status: Backlog

Development

Successfully merging this pull request may close these issues.

Deconflation endpoint Add option to provide clique leaders in addition to the combined clique

2 participants

@gaurav
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

Add clique leaders option - #350

Draft
gaurav wants to merge 37 commits into
mainfrom
add-clique-leaders-option
Draft

Add clique leaders option#350
gaurav wants to merge 37 commits into
mainfrom
add-clique-leaders-option

Conversation

@gaurav

@gauravgaurav commented Dec 15, 2025

Copy link
Copy Markdown
Collaborator

This PR closes#320 by adding an include_clique_leaders option on normalization. This may be a way to fix#340. Also renames some variables and adds some LLM-generated function documentation.

This PR adds a new flag include_clique_leaders that can be set on both GET and POST /get_normalized_nodes endpoints. Activating this endpoint adds a clique_leaders key to each normalized identifier that includes a list of all the clique leaders in this clique, along with their name, type and taxa, and (if the appropriate flags are turned on) descriptions. This doesn't currently include all the identifiers in each clique, but that should be added without too much extra bother.

WIP

  • Would it be useful to include the list of identifiers for each clique leader? That will require some additional finagling with the code, but it shouldn't be too problematic.
  • Is clique_leaders really the best thing to call this thing? These are all clique leader identifiers, but maybe conflation_leaders or something else would be better?
  • Add tests to Babel Validator

Example

Example output for NCBIGene:1756 is included below. Note that the conflation type is included (e.g. "conflation": "GeneProtein") and that clique_leaders is a list of the cliques leaders ordered in their position in the normalization.

{
"NCBIGene:1756": {
"id": {
"identifier": "NCBIGene:1756",
"label": "DMD",
"description": "dystrophin"
},
"equivalent_identifiers": [
{
"identifier": "NCBIGene:1756",
"label": "DMD",
"description": "dystrophin",
"taxa": [
"NCBITaxon:9606"
],
"type": "biolink:Gene"
},
{
"identifier": "ENSEMBL:ENSG00000198947",
"type": "biolink:Gene"
},
{
"identifier": "HGNC:2928",
"label": "DMD",
"type": "biolink:Gene"
},
{
"identifier": "OMIM:300377",
"type": "biolink:Gene"
},
{
"identifier": "UMLS:C1414083",
"label": "DMD gene",
"type": "biolink:Gene"
},
{
"identifier": "UniProtKB:A0A087WV90",
"label": "A0A087WV90_HUMAN Dystrophin (trembl)",
"taxa": [
"NCBITaxon:9606"
],
"type": "biolink:Protein"
},
{
"identifier": "UniProtKB:A0A0S2Z3B5",
"label": "A0A0S2Z3B5_HUMAN Dystrophin isoform 2 (trembl)",
"taxa": [
"NCBITaxon:9606"
],
"type": "biolink:Protein"
},
{
"identifier": "UniProtKB:A0A0S2Z3J7",
"label": "A0A0S2Z3J7_HUMAN Dystrophin isoform 1 (Fragment) (trembl)",
"taxa": [
"NCBITaxon:9606"
],
"type": "biolink:Protein"
},
{
"identifier": "UniProtKB:A0A5H1ZRP9",
"label": "A0A5H1ZRP9_HUMAN Dystrophin (trembl)",
"taxa": [
"NCBITaxon:9606"
],
"type": "biolink:Protein"
},
{
"identifier": "UniProtKB:A0A5H1ZRQ1",
"label": "A0A5H1ZRQ1_HUMAN Dystrophin (trembl)",
"taxa": [
"NCBITaxon:9606"
],
"type": "biolink:Protein"
},
{
"identifier": "UniProtKB:A0A5H1ZRQ8",
"label": "A0A5H1ZRQ8_HUMAN Dystrophin (trembl)",
"taxa": [
"NCBITaxon:9606"
],
"type": "biolink:Protein"
},
{
"identifier": "UniProtKB:A0A5H1ZRR9",
"label": "A0A5H1ZRR9_HUMAN Dystrophin (trembl)",
"taxa": [
"NCBITaxon:9606"
],
"type": "biolink:Protein"
},
{
"identifier": "UniProtKB:A0A804HKY9",
"label": "A0A804HKY9_HUMAN Dystrophin (trembl)",
"taxa": [
"NCBITaxon:9606"
],
"type": "biolink:Protein"
},
{
"identifier": "UniProtKB:A7E212",
"label": "A7E212_HUMAN Dystrophin (trembl)",
"taxa": [
"NCBITaxon:9606"
],
"type": "biolink:Protein"
},
{
"identifier": "UniProtKB:P11532",
"label": "DMD_HUMAN Dystrophin (sprot)",
"taxa": [
"NCBITaxon:9606"
],
"type": "biolink:Protein"
},
{
"identifier": "PR:P11532",
"label": "dystrophin (human)",
"description": "A dystrophin that is encoded in the genome of human.",
"type": "biolink:Protein"
},
{
"identifier": "UMLS:C1437024",
"label": "DMD protein, human",
"type": "biolink:Protein"
},
{
"identifier": "MESH:C484258",
"label": "DMD protein, human",
"type": "biolink:Protein"
},
{
"identifier": "UniProtKB:Q16484",
"label": "Q16484_HUMAN DMD protein (Fragment) (trembl)",
"taxa": [
"NCBITaxon:9606"
],
"type": "biolink:Protein"
},
{
"identifier": "UniProtKB:Q4G0X0",
"label": "Q4G0X0_HUMAN DMD protein (trembl)",
"taxa": [
"NCBITaxon:9606"
],
"type": "biolink:Protein"
},
{
"identifier": "ENSEMBL:ENSP00000288447",
"type": "biolink:Protein"
},
{
"identifier": "ENSEMBL:ENSP00000288447.4",
"type": "biolink:Protein"
}
],
"descriptions": [
"dystrophin",
"A dystrophin that is encoded in the genome of human."
],
"taxa": [
"NCBITaxon:9606"
],
"clique_leaders": [
{
"identifier": "NCBIGene:1756",
"conflation": "GeneProtein",
"label": "DMD",
"description": [
"dystrophin"
],
"taxa": [
"NCBITaxon:9606"
],
"type": "biolink:Gene"
},
{
"identifier": "UniProtKB:A0A087WV90",
"conflation": "GeneProtein",
"label": "A0A087WV90_HUMAN Dystrophin (trembl)",
"taxa": [
"NCBITaxon:9606"
],
"type": "biolink:Protein"
},
{
"identifier": "UniProtKB:A0A0S2Z3B5",
"conflation": "GeneProtein",
"label": "A0A0S2Z3B5_HUMAN Dystrophin isoform 2 (trembl)",
"taxa": [
"NCBITaxon:9606"
],
"type": "biolink:Protein"
},
{
"identifier": "UniProtKB:A0A0S2Z3J7",
"conflation": "GeneProtein",
"label": "A0A0S2Z3J7_HUMAN Dystrophin isoform 1 (Fragment) (trembl)",
"taxa": [
"NCBITaxon:9606"
],
"type": "biolink:Protein"
},
{
"identifier": "UniProtKB:A0A5H1ZRP9",
"conflation": "GeneProtein",
"label": "A0A5H1ZRP9_HUMAN Dystrophin (trembl)",
"taxa": [
"NCBITaxon:9606"
],
"type": "biolink:Protein"
},
{
"identifier": "UniProtKB:A0A5H1ZRQ1",
"conflation": "GeneProtein",
"label": "A0A5H1ZRQ1_HUMAN Dystrophin (trembl)",
"taxa": [
"NCBITaxon:9606"
],
"type": "biolink:Protein"
},
{
"identifier": "UniProtKB:A0A5H1ZRQ8",
"conflation": "GeneProtein",
"label": "A0A5H1ZRQ8_HUMAN Dystrophin (trembl)",
"taxa": [
"NCBITaxon:9606"
],
"type": "biolink:Protein"
},
{
"identifier": "UniProtKB:A0A5H1ZRR9",
"conflation": "GeneProtein",
"label": "A0A5H1ZRR9_HUMAN Dystrophin (trembl)",
"taxa": [
"NCBITaxon:9606"
],
"type": "biolink:Protein"
},
{
"identifier": "UniProtKB:A0A804HKY9",
"conflation": "GeneProtein",
"label": "A0A804HKY9_HUMAN Dystrophin (trembl)",
"taxa": [
"NCBITaxon:9606"
],
"type": "biolink:Protein"
},
{
"identifier": "UniProtKB:A7E212",
"conflation": "GeneProtein",
"label": "A7E212_HUMAN Dystrophin (trembl)",
"taxa": [
"NCBITaxon:9606"
],
"type": "biolink:Protein"
},
{
"identifier": "UniProtKB:P11532",
"conflation": "GeneProtein",
"label": "DMD_HUMAN Dystrophin (sprot)",
"taxa": [
"NCBITaxon:9606"
],
"type": "biolink:Protein"
},
{
"identifier": "UniProtKB:Q16484",
"conflation": "GeneProtein",
"label": "Q16484_HUMAN DMD protein (Fragment) (trembl)",
"taxa": [
"NCBITaxon:9606"
],
"type": "biolink:Protein"
},
{
"identifier": "UniProtKB:Q4G0X0",
"conflation": "GeneProtein",
"label": "Q4G0X0_HUMAN DMD protein (trembl)",
"taxa": [
"NCBITaxon:9606"
],
"type": "biolink:Protein"
}
],
"type": [
"biolink:Gene",
"biolink:GeneOrGeneProduct",
"biolink:GenomicEntity",
"biolink:ChemicalEntityOrGeneOrGeneProduct",
"biolink:PhysicalEssence",
"biolink:OntologyClass",
"biolink:BiologicalEntity",
"biolink:ThingWithTaxon",
"biolink:NamedThing",
"biolink:PhysicalEssenceOrOccurrent",
"biolink:MacromolecularMachineMixin",
"biolink:Protein",
"biolink:GeneProductMixin",
"biolink:Polypeptide",
"biolink:ChemicalEntityOrProteinOrPolypeptide"
],
"information_content": 79.9
}
}

@gauravgaurav moved this from Backlog to In progress in Babel sprintsFeb 18, 2026
@gaurav
gaurav changed the base branch from master to add-nodenorm-version-to-statusFebruary 20, 2026 00:24
Base automatically changed from add-nodenorm-version-to-status to masterFebruary 20, 2026 00:31
@gaurav
gaurav marked this pull request as ready for review February 25, 2026 01:39
@gaurav
gaurav requested a review from CopilotFebruary 25, 2026 01:40

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This PR adds a new include_clique_leaders parameter to the /get_normalized_nodes endpoints (both GET and POST) to support deconflation use cases. When enabled, the API returns detailed information about individual clique leaders for conflated identifiers, helping users understand which cliques are being combined during gene/protein and drug/chemical conflation.

Changes:

  • Added include_clique_leaders boolean parameter to normalization endpoints
  • Modified normalization logic to collect and output clique leader information when requested
  • Updated several variable names for clarity (e.g., typestypes_with_ancestors)
  • Added LLM-generated docstrings to the get_eqids_and_types function

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 4 comments.

FileDescription
node_normalizer/server.pyAdded include_clique_leaders query parameter to GET endpoint and passed it through to normalization logic
node_normalizer/model/input.pyAdded include_clique_leaders field to CurieList input model for POST endpoint
node_normalizer/set_id.pyUpdated call to get_normalized_nodes() to explicitly pass include_clique_leaders=False
node_normalizer/normalizer.pyCore implementation: collects clique leaders when conflation is enabled, generates clique leader output with metadata (identifier, conflation type, label, description, taxa, type), and includes it in response
Comments suppressed due to low confidence (1)

node_normalizer/normalizer.py:558

  • The docstring for this function is incomplete and doesn't describe the parameters, including the new include_clique_leaders parameter. Given that the codebase uses docstring conventions (as seen in get_eqids_and_types and other functions), this function's docstring should be updated to document all parameters and their purposes, particularly the new optional parameters that control output formatting.
 """
Get value(s) for key(s) using redis MGET
"""

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment threadnode_normalizer/normalizer.py Outdated
Comment threadnode_normalizer/normalizer.py
Comment threadnode_normalizer/normalizer.py Outdated
Comment on lines +862 to +881
if clique_leaders:
for conflation_type in clique_leaders:
if canonical_id in clique_leaders[conflation_type] and eqid["i"] in clique_leaders[conflation_type][canonical_id]:
clique_leader_output = {
"identifier": eqid["i"],
"conflation": conflation_type,
}
if "label" in eq_item:
clique_leader_output["label"] = eq_item["label"]

# For description, taxa and type, we could read them from eq_item, but that
# is only set if the appropriate flag was turned on. For completeness, let's
# try picking them up if they've been passed to us at all.
if "d" in eqid and len(eqid["d"]) > 0:
clique_leader_output["description"] = eqid["d"]
if "t" in eqid and eqid["t"]:
clique_leader_output["taxa"] = eqid["t"]
if 'types' in eqid:
clique_leader_output["type"] = eqid['types'][-1]
clique_leaders_output.append(clique_leader_output)

CopilotAIFeb 25, 2026

Copy link

Choose a reason for hiding this comment

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

The loop structure here could be optimized. Currently, for every equivalent identifier, the code checks all conflation types to see if it's a clique leader. This could be improved by pre-computing a set of clique leaders for faster lookup, especially since the print statement on line 861 will execute for every single equivalent identifier in the response, which could be hundreds or thousands of times for large queries. Consider moving the clique leader check logic outside the main loop or optimizing it with a set-based lookup.

Copilot uses AI. Check for mistakes.
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
@gaurav
gaurav marked this pull request as draft February 25, 2026 01:48
@gauravgaurav mentioned this pull request Feb 25, 2026
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: In progress
Status: Backlog

Development

Successfully merging this pull request may close these issues.

Deconflation endpoint Add option to provide clique leaders in addition to the combined clique

2 participants

@gaurav
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Add clique leaders option - #350

Draft
gaurav wants to merge 37 commits into
mainfrom
add-clique-leaders-option
Draft

Add clique leaders option#350
gaurav wants to merge 37 commits into
mainfrom
add-clique-leaders-option

Conversation

@gaurav

@gauravgaurav commented Dec 15, 2025

Copy link
Copy Markdown
Collaborator

This PR closes#320 by adding an include_clique_leaders option on normalization. This may be a way to fix#340. Also renames some variables and adds some LLM-generated function documentation.

This PR adds a new flag include_clique_leaders that can be set on both GET and POST /get_normalized_nodes endpoints. Activating this endpoint adds a clique_leaders key to each normalized identifier that includes a list of all the clique leaders in this clique, along with their name, type and taxa, and (if the appropriate flags are turned on) descriptions. This doesn't currently include all the identifiers in each clique, but that should be added without too much extra bother.

WIP

  • Would it be useful to include the list of identifiers for each clique leader? That will require some additional finagling with the code, but it shouldn't be too problematic.
  • Is clique_leaders really the best thing to call this thing? These are all clique leader identifiers, but maybe conflation_leaders or something else would be better?
  • Add tests to Babel Validator

Example

Example output for NCBIGene:1756 is included below. Note that the conflation type is included (e.g. "conflation": "GeneProtein") and that clique_leaders is a list of the cliques leaders ordered in their position in the normalization.

{
"NCBIGene:1756": {
"id": {
"identifier": "NCBIGene:1756",
"label": "DMD",
"description": "dystrophin"
},
"equivalent_identifiers": [
{
"identifier": "NCBIGene:1756",
"label": "DMD",
"description": "dystrophin",
"taxa": [
"NCBITaxon:9606"
],
"type": "biolink:Gene"
},
{
"identifier": "ENSEMBL:ENSG00000198947",
"type": "biolink:Gene"
},
{
"identifier": "HGNC:2928",
"label": "DMD",
"type": "biolink:Gene"
},
{
"identifier": "OMIM:300377",
"type": "biolink:Gene"
},
{
"identifier": "UMLS:C1414083",
"label": "DMD gene",
"type": "biolink:Gene"
},
{
"identifier": "UniProtKB:A0A087WV90",
"label": "A0A087WV90_HUMAN Dystrophin (trembl)",
"taxa": [
"NCBITaxon:9606"
],
"type": "biolink:Protein"
},
{
"identifier": "UniProtKB:A0A0S2Z3B5",
"label": "A0A0S2Z3B5_HUMAN Dystrophin isoform 2 (trembl)",
"taxa": [
"NCBITaxon:9606"
],
"type": "biolink:Protein"
},
{
"identifier": "UniProtKB:A0A0S2Z3J7",
"label": "A0A0S2Z3J7_HUMAN Dystrophin isoform 1 (Fragment) (trembl)",
"taxa": [
"NCBITaxon:9606"
],
"type": "biolink:Protein"
},
{
"identifier": "UniProtKB:A0A5H1ZRP9",
"label": "A0A5H1ZRP9_HUMAN Dystrophin (trembl)",
"taxa": [
"NCBITaxon:9606"
],
"type": "biolink:Protein"
},
{
"identifier": "UniProtKB:A0A5H1ZRQ1",
"label": "A0A5H1ZRQ1_HUMAN Dystrophin (trembl)",
"taxa": [
"NCBITaxon:9606"
],
"type": "biolink:Protein"
},
{
"identifier": "UniProtKB:A0A5H1ZRQ8",
"label": "A0A5H1ZRQ8_HUMAN Dystrophin (trembl)",
"taxa": [
"NCBITaxon:9606"
],
"type": "biolink:Protein"
},
{
"identifier": "UniProtKB:A0A5H1ZRR9",
"label": "A0A5H1ZRR9_HUMAN Dystrophin (trembl)",
"taxa": [
"NCBITaxon:9606"
],
"type": "biolink:Protein"
},
{
"identifier": "UniProtKB:A0A804HKY9",
"label": "A0A804HKY9_HUMAN Dystrophin (trembl)",
"taxa": [
"NCBITaxon:9606"
],
"type": "biolink:Protein"
},
{
"identifier": "UniProtKB:A7E212",
"label": "A7E212_HUMAN Dystrophin (trembl)",
"taxa": [
"NCBITaxon:9606"
],
"type": "biolink:Protein"
},
{
"identifier": "UniProtKB:P11532",
"label": "DMD_HUMAN Dystrophin (sprot)",
"taxa": [
"NCBITaxon:9606"
],
"type": "biolink:Protein"
},
{
"identifier": "PR:P11532",
"label": "dystrophin (human)",
"description": "A dystrophin that is encoded in the genome of human.",
"type": "biolink:Protein"
},
{
"identifier": "UMLS:C1437024",
"label": "DMD protein, human",
"type": "biolink:Protein"
},
{
"identifier": "MESH:C484258",
"label": "DMD protein, human",
"type": "biolink:Protein"
},
{
"identifier": "UniProtKB:Q16484",
"label": "Q16484_HUMAN DMD protein (Fragment) (trembl)",
"taxa": [
"NCBITaxon:9606"
],
"type": "biolink:Protein"
},
{
"identifier": "UniProtKB:Q4G0X0",
"label": "Q4G0X0_HUMAN DMD protein (trembl)",
"taxa": [
"NCBITaxon:9606"
],
"type": "biolink:Protein"
},
{
"identifier": "ENSEMBL:ENSP00000288447",
"type": "biolink:Protein"
},
{
"identifier": "ENSEMBL:ENSP00000288447.4",
"type": "biolink:Protein"
}
],
"descriptions": [
"dystrophin",
"A dystrophin that is encoded in the genome of human."
],
"taxa": [
"NCBITaxon:9606"
],
"clique_leaders": [
{
"identifier": "NCBIGene:1756",
"conflation": "GeneProtein",
"label": "DMD",
"description": [
"dystrophin"
],
"taxa": [
"NCBITaxon:9606"
],
"type": "biolink:Gene"
},
{
"identifier": "UniProtKB:A0A087WV90",
"conflation": "GeneProtein",
"label": "A0A087WV90_HUMAN Dystrophin (trembl)",
"taxa": [
"NCBITaxon:9606"
],
"type": "biolink:Protein"
},
{
"identifier": "UniProtKB:A0A0S2Z3B5",
"conflation": "GeneProtein",
"label": "A0A0S2Z3B5_HUMAN Dystrophin isoform 2 (trembl)",
"taxa": [
"NCBITaxon:9606"
],
"type": "biolink:Protein"
},
{
"identifier": "UniProtKB:A0A0S2Z3J7",
"conflation": "GeneProtein",
"label": "A0A0S2Z3J7_HUMAN Dystrophin isoform 1 (Fragment) (trembl)",
"taxa": [
"NCBITaxon:9606"
],
"type": "biolink:Protein"
},
{
"identifier": "UniProtKB:A0A5H1ZRP9",
"conflation": "GeneProtein",
"label": "A0A5H1ZRP9_HUMAN Dystrophin (trembl)",
"taxa": [
"NCBITaxon:9606"
],
"type": "biolink:Protein"
},
{
"identifier": "UniProtKB:A0A5H1ZRQ1",
"conflation": "GeneProtein",
"label": "A0A5H1ZRQ1_HUMAN Dystrophin (trembl)",
"taxa": [
"NCBITaxon:9606"
],
"type": "biolink:Protein"
},
{
"identifier": "UniProtKB:A0A5H1ZRQ8",
"conflation": "GeneProtein",
"label": "A0A5H1ZRQ8_HUMAN Dystrophin (trembl)",
"taxa": [
"NCBITaxon:9606"
],
"type": "biolink:Protein"
},
{
"identifier": "UniProtKB:A0A5H1ZRR9",
"conflation": "GeneProtein",
"label": "A0A5H1ZRR9_HUMAN Dystrophin (trembl)",
"taxa": [
"NCBITaxon:9606"
],
"type": "biolink:Protein"
},
{
"identifier": "UniProtKB:A0A804HKY9",
"conflation": "GeneProtein",
"label": "A0A804HKY9_HUMAN Dystrophin (trembl)",
"taxa": [
"NCBITaxon:9606"
],
"type": "biolink:Protein"
},
{
"identifier": "UniProtKB:A7E212",
"conflation": "GeneProtein",
"label": "A7E212_HUMAN Dystrophin (trembl)",
"taxa": [
"NCBITaxon:9606"
],
"type": "biolink:Protein"
},
{
"identifier": "UniProtKB:P11532",
"conflation": "GeneProtein",
"label": "DMD_HUMAN Dystrophin (sprot)",
"taxa": [
"NCBITaxon:9606"
],
"type": "biolink:Protein"
},
{
"identifier": "UniProtKB:Q16484",
"conflation": "GeneProtein",
"label": "Q16484_HUMAN DMD protein (Fragment) (trembl)",
"taxa": [
"NCBITaxon:9606"
],
"type": "biolink:Protein"
},
{
"identifier": "UniProtKB:Q4G0X0",
"conflation": "GeneProtein",
"label": "Q4G0X0_HUMAN DMD protein (trembl)",
"taxa": [
"NCBITaxon:9606"
],
"type": "biolink:Protein"
}
],
"type": [
"biolink:Gene",
"biolink:GeneOrGeneProduct",
"biolink:GenomicEntity",
"biolink:ChemicalEntityOrGeneOrGeneProduct",
"biolink:PhysicalEssence",
"biolink:OntologyClass",
"biolink:BiologicalEntity",
"biolink:ThingWithTaxon",
"biolink:NamedThing",
"biolink:PhysicalEssenceOrOccurrent",
"biolink:MacromolecularMachineMixin",
"biolink:Protein",
"biolink:GeneProductMixin",
"biolink:Polypeptide",
"biolink:ChemicalEntityOrProteinOrPolypeptide"
],
"information_content": 79.9
}
}

@gauravgaurav moved this from Backlog to In progress in Babel sprintsFeb 18, 2026
@gaurav
gaurav changed the base branch from master to add-nodenorm-version-to-statusFebruary 20, 2026 00:24
Base automatically changed from add-nodenorm-version-to-status to masterFebruary 20, 2026 00:31
@gaurav
gaurav marked this pull request as ready for review February 25, 2026 01:39
@gaurav
gaurav requested a review from CopilotFebruary 25, 2026 01:40

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This PR adds a new include_clique_leaders parameter to the /get_normalized_nodes endpoints (both GET and POST) to support deconflation use cases. When enabled, the API returns detailed information about individual clique leaders for conflated identifiers, helping users understand which cliques are being combined during gene/protein and drug/chemical conflation.

Changes:

  • Added include_clique_leaders boolean parameter to normalization endpoints
  • Modified normalization logic to collect and output clique leader information when requested
  • Updated several variable names for clarity (e.g., typestypes_with_ancestors)
  • Added LLM-generated docstrings to the get_eqids_and_types function

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 4 comments.

FileDescription
node_normalizer/server.pyAdded include_clique_leaders query parameter to GET endpoint and passed it through to normalization logic
node_normalizer/model/input.pyAdded include_clique_leaders field to CurieList input model for POST endpoint
node_normalizer/set_id.pyUpdated call to get_normalized_nodes() to explicitly pass include_clique_leaders=False
node_normalizer/normalizer.pyCore implementation: collects clique leaders when conflation is enabled, generates clique leader output with metadata (identifier, conflation type, label, description, taxa, type), and includes it in response
Comments suppressed due to low confidence (1)

node_normalizer/normalizer.py:558

  • The docstring for this function is incomplete and doesn't describe the parameters, including the new include_clique_leaders parameter. Given that the codebase uses docstring conventions (as seen in get_eqids_and_types and other functions), this function's docstring should be updated to document all parameters and their purposes, particularly the new optional parameters that control output formatting.
 """
Get value(s) for key(s) using redis MGET
"""

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment threadnode_normalizer/normalizer.py Outdated
Comment threadnode_normalizer/normalizer.py
Comment threadnode_normalizer/normalizer.py Outdated
Comment on lines +862 to +881
if clique_leaders:
for conflation_type in clique_leaders:
if canonical_id in clique_leaders[conflation_type] and eqid["i"] in clique_leaders[conflation_type][canonical_id]:
clique_leader_output = {
"identifier": eqid["i"],
"conflation": conflation_type,
}
if "label" in eq_item:
clique_leader_output["label"] = eq_item["label"]

# For description, taxa and type, we could read them from eq_item, but that
# is only set if the appropriate flag was turned on. For completeness, let's
# try picking them up if they've been passed to us at all.
if "d" in eqid and len(eqid["d"]) > 0:
clique_leader_output["description"] = eqid["d"]
if "t" in eqid and eqid["t"]:
clique_leader_output["taxa"] = eqid["t"]
if 'types' in eqid:
clique_leader_output["type"] = eqid['types'][-1]
clique_leaders_output.append(clique_leader_output)

CopilotAIFeb 25, 2026

Copy link

Choose a reason for hiding this comment

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

The loop structure here could be optimized. Currently, for every equivalent identifier, the code checks all conflation types to see if it's a clique leader. This could be improved by pre-computing a set of clique leaders for faster lookup, especially since the print statement on line 861 will execute for every single equivalent identifier in the response, which could be hundreds or thousands of times for large queries. Consider moving the clique leader check logic outside the main loop or optimizing it with a set-based lookup.

Copilot uses AI. Check for mistakes.
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
@gaurav
gaurav marked this pull request as draft February 25, 2026 01:48
@gauravgaurav mentioned this pull request Feb 25, 2026
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: In progress
Status: Backlog

Development

Successfully merging this pull request may close these issues.

Deconflation endpoint Add option to provide clique leaders in addition to the combined clique

2 participants

@gaurav
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Add clique leaders option - #350

Draft
gaurav wants to merge 37 commits into
mainfrom
add-clique-leaders-option
Draft

Add clique leaders option#350
gaurav wants to merge 37 commits into
mainfrom
add-clique-leaders-option

Conversation

@gaurav

@gauravgaurav commented Dec 15, 2025

Copy link
Copy Markdown
Collaborator

This PR closes#320 by adding an include_clique_leaders option on normalization. This may be a way to fix#340. Also renames some variables and adds some LLM-generated function documentation.

This PR adds a new flag include_clique_leaders that can be set on both GET and POST /get_normalized_nodes endpoints. Activating this endpoint adds a clique_leaders key to each normalized identifier that includes a list of all the clique leaders in this clique, along with their name, type and taxa, and (if the appropriate flags are turned on) descriptions. This doesn't currently include all the identifiers in each clique, but that should be added without too much extra bother.

WIP

  • Would it be useful to include the list of identifiers for each clique leader? That will require some additional finagling with the code, but it shouldn't be too problematic.
  • Is clique_leaders really the best thing to call this thing? These are all clique leader identifiers, but maybe conflation_leaders or something else would be better?
  • Add tests to Babel Validator

Example

Example output for NCBIGene:1756 is included below. Note that the conflation type is included (e.g. "conflation": "GeneProtein") and that clique_leaders is a list of the cliques leaders ordered in their position in the normalization.

{
"NCBIGene:1756": {
"id": {
"identifier": "NCBIGene:1756",
"label": "DMD",
"description": "dystrophin"
},
"equivalent_identifiers": [
{
"identifier": "NCBIGene:1756",
"label": "DMD",
"description": "dystrophin",
"taxa": [
"NCBITaxon:9606"
],
"type": "biolink:Gene"
},
{
"identifier": "ENSEMBL:ENSG00000198947",
"type": "biolink:Gene"
},
{
"identifier": "HGNC:2928",
"label": "DMD",
"type": "biolink:Gene"
},
{
"identifier": "OMIM:300377",
"type": "biolink:Gene"
},
{
"identifier": "UMLS:C1414083",
"label": "DMD gene",
"type": "biolink:Gene"
},
{
"identifier": "UniProtKB:A0A087WV90",
"label": "A0A087WV90_HUMAN Dystrophin (trembl)",
"taxa": [
"NCBITaxon:9606"
],
"type": "biolink:Protein"
},
{
"identifier": "UniProtKB:A0A0S2Z3B5",
"label": "A0A0S2Z3B5_HUMAN Dystrophin isoform 2 (trembl)",
"taxa": [
"NCBITaxon:9606"
],
"type": "biolink:Protein"
},
{
"identifier": "UniProtKB:A0A0S2Z3J7",
"label": "A0A0S2Z3J7_HUMAN Dystrophin isoform 1 (Fragment) (trembl)",
"taxa": [
"NCBITaxon:9606"
],
"type": "biolink:Protein"
},
{
"identifier": "UniProtKB:A0A5H1ZRP9",
"label": "A0A5H1ZRP9_HUMAN Dystrophin (trembl)",
"taxa": [
"NCBITaxon:9606"
],
"type": "biolink:Protein"
},
{
"identifier": "UniProtKB:A0A5H1ZRQ1",
"label": "A0A5H1ZRQ1_HUMAN Dystrophin (trembl)",
"taxa": [
"NCBITaxon:9606"
],
"type": "biolink:Protein"
},
{
"identifier": "UniProtKB:A0A5H1ZRQ8",
"label": "A0A5H1ZRQ8_HUMAN Dystrophin (trembl)",
"taxa": [
"NCBITaxon:9606"
],
"type": "biolink:Protein"
},
{
"identifier": "UniProtKB:A0A5H1ZRR9",
"label": "A0A5H1ZRR9_HUMAN Dystrophin (trembl)",
"taxa": [
"NCBITaxon:9606"
],
"type": "biolink:Protein"
},
{
"identifier": "UniProtKB:A0A804HKY9",
"label": "A0A804HKY9_HUMAN Dystrophin (trembl)",
"taxa": [
"NCBITaxon:9606"
],
"type": "biolink:Protein"
},
{
"identifier": "UniProtKB:A7E212",
"label": "A7E212_HUMAN Dystrophin (trembl)",
"taxa": [
"NCBITaxon:9606"
],
"type": "biolink:Protein"
},
{
"identifier": "UniProtKB:P11532",
"label": "DMD_HUMAN Dystrophin (sprot)",
"taxa": [
"NCBITaxon:9606"
],
"type": "biolink:Protein"
},
{
"identifier": "PR:P11532",
"label": "dystrophin (human)",
"description": "A dystrophin that is encoded in the genome of human.",
"type": "biolink:Protein"
},
{
"identifier": "UMLS:C1437024",
"label": "DMD protein, human",
"type": "biolink:Protein"
},
{
"identifier": "MESH:C484258",
"label": "DMD protein, human",
"type": "biolink:Protein"
},
{
"identifier": "UniProtKB:Q16484",
"label": "Q16484_HUMAN DMD protein (Fragment) (trembl)",
"taxa": [
"NCBITaxon:9606"
],
"type": "biolink:Protein"
},
{
"identifier": "UniProtKB:Q4G0X0",
"label": "Q4G0X0_HUMAN DMD protein (trembl)",
"taxa": [
"NCBITaxon:9606"
],
"type": "biolink:Protein"
},
{
"identifier": "ENSEMBL:ENSP00000288447",
"type": "biolink:Protein"
},
{
"identifier": "ENSEMBL:ENSP00000288447.4",
"type": "biolink:Protein"
}
],
"descriptions": [
"dystrophin",
"A dystrophin that is encoded in the genome of human."
],
"taxa": [
"NCBITaxon:9606"
],
"clique_leaders": [
{
"identifier": "NCBIGene:1756",
"conflation": "GeneProtein",
"label": "DMD",
"description": [
"dystrophin"
],
"taxa": [
"NCBITaxon:9606"
],
"type": "biolink:Gene"
},
{
"identifier": "UniProtKB:A0A087WV90",
"conflation": "GeneProtein",
"label": "A0A087WV90_HUMAN Dystrophin (trembl)",
"taxa": [
"NCBITaxon:9606"
],
"type": "biolink:Protein"
},
{
"identifier": "UniProtKB:A0A0S2Z3B5",
"conflation": "GeneProtein",
"label": "A0A0S2Z3B5_HUMAN Dystrophin isoform 2 (trembl)",
"taxa": [
"NCBITaxon:9606"
],
"type": "biolink:Protein"
},
{
"identifier": "UniProtKB:A0A0S2Z3J7",
"conflation": "GeneProtein",
"label": "A0A0S2Z3J7_HUMAN Dystrophin isoform 1 (Fragment) (trembl)",
"taxa": [
"NCBITaxon:9606"
],
"type": "biolink:Protein"
},
{
"identifier": "UniProtKB:A0A5H1ZRP9",
"conflation": "GeneProtein",
"label": "A0A5H1ZRP9_HUMAN Dystrophin (trembl)",
"taxa": [
"NCBITaxon:9606"
],
"type": "biolink:Protein"
},
{
"identifier": "UniProtKB:A0A5H1ZRQ1",
"conflation": "GeneProtein",
"label": "A0A5H1ZRQ1_HUMAN Dystrophin (trembl)",
"taxa": [
"NCBITaxon:9606"
],
"type": "biolink:Protein"
},
{
"identifier": "UniProtKB:A0A5H1ZRQ8",
"conflation": "GeneProtein",
"label": "A0A5H1ZRQ8_HUMAN Dystrophin (trembl)",
"taxa": [
"NCBITaxon:9606"
],
"type": "biolink:Protein"
},
{
"identifier": "UniProtKB:A0A5H1ZRR9",
"conflation": "GeneProtein",
"label": "A0A5H1ZRR9_HUMAN Dystrophin (trembl)",
"taxa": [
"NCBITaxon:9606"
],
"type": "biolink:Protein"
},
{
"identifier": "UniProtKB:A0A804HKY9",
"conflation": "GeneProtein",
"label": "A0A804HKY9_HUMAN Dystrophin (trembl)",
"taxa": [
"NCBITaxon:9606"
],
"type": "biolink:Protein"
},
{
"identifier": "UniProtKB:A7E212",
"conflation": "GeneProtein",
"label": "A7E212_HUMAN Dystrophin (trembl)",
"taxa": [
"NCBITaxon:9606"
],
"type": "biolink:Protein"
},
{
"identifier": "UniProtKB:P11532",
"conflation": "GeneProtein",
"label": "DMD_HUMAN Dystrophin (sprot)",
"taxa": [
"NCBITaxon:9606"
],
"type": "biolink:Protein"
},
{
"identifier": "UniProtKB:Q16484",
"conflation": "GeneProtein",
"label": "Q16484_HUMAN DMD protein (Fragment) (trembl)",
"taxa": [
"NCBITaxon:9606"
],
"type": "biolink:Protein"
},
{
"identifier": "UniProtKB:Q4G0X0",
"conflation": "GeneProtein",
"label": "Q4G0X0_HUMAN DMD protein (trembl)",
"taxa": [
"NCBITaxon:9606"
],
"type": "biolink:Protein"
}
],
"type": [
"biolink:Gene",
"biolink:GeneOrGeneProduct",
"biolink:GenomicEntity",
"biolink:ChemicalEntityOrGeneOrGeneProduct",
"biolink:PhysicalEssence",
"biolink:OntologyClass",
"biolink:BiologicalEntity",
"biolink:ThingWithTaxon",
"biolink:NamedThing",
"biolink:PhysicalEssenceOrOccurrent",
"biolink:MacromolecularMachineMixin",
"biolink:Protein",
"biolink:GeneProductMixin",
"biolink:Polypeptide",
"biolink:ChemicalEntityOrProteinOrPolypeptide"
],
"information_content": 79.9
}
}

@gauravgaurav moved this from Backlog to In progress in Babel sprintsFeb 18, 2026
@gaurav
gaurav changed the base branch from master to add-nodenorm-version-to-statusFebruary 20, 2026 00:24
Base automatically changed from add-nodenorm-version-to-status to masterFebruary 20, 2026 00:31
@gaurav
gaurav marked this pull request as ready for review February 25, 2026 01:39
@gaurav
gaurav requested a review from CopilotFebruary 25, 2026 01:40

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This PR adds a new include_clique_leaders parameter to the /get_normalized_nodes endpoints (both GET and POST) to support deconflation use cases. When enabled, the API returns detailed information about individual clique leaders for conflated identifiers, helping users understand which cliques are being combined during gene/protein and drug/chemical conflation.

Changes:

  • Added include_clique_leaders boolean parameter to normalization endpoints
  • Modified normalization logic to collect and output clique leader information when requested
  • Updated several variable names for clarity (e.g., typestypes_with_ancestors)
  • Added LLM-generated docstrings to the get_eqids_and_types function

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 4 comments.

FileDescription
node_normalizer/server.pyAdded include_clique_leaders query parameter to GET endpoint and passed it through to normalization logic
node_normalizer/model/input.pyAdded include_clique_leaders field to CurieList input model for POST endpoint
node_normalizer/set_id.pyUpdated call to get_normalized_nodes() to explicitly pass include_clique_leaders=False
node_normalizer/normalizer.pyCore implementation: collects clique leaders when conflation is enabled, generates clique leader output with metadata (identifier, conflation type, label, description, taxa, type), and includes it in response
Comments suppressed due to low confidence (1)

node_normalizer/normalizer.py:558

  • The docstring for this function is incomplete and doesn't describe the parameters, including the new include_clique_leaders parameter. Given that the codebase uses docstring conventions (as seen in get_eqids_and_types and other functions), this function's docstring should be updated to document all parameters and their purposes, particularly the new optional parameters that control output formatting.
 """
Get value(s) for key(s) using redis MGET
"""

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment threadnode_normalizer/normalizer.py Outdated
Comment threadnode_normalizer/normalizer.py
Comment threadnode_normalizer/normalizer.py Outdated
Comment on lines +862 to +881
if clique_leaders:
for conflation_type in clique_leaders:
if canonical_id in clique_leaders[conflation_type] and eqid["i"] in clique_leaders[conflation_type][canonical_id]:
clique_leader_output = {
"identifier": eqid["i"],
"conflation": conflation_type,
}
if "label" in eq_item:
clique_leader_output["label"] = eq_item["label"]

# For description, taxa and type, we could read them from eq_item, but that
# is only set if the appropriate flag was turned on. For completeness, let's
# try picking them up if they've been passed to us at all.
if "d" in eqid and len(eqid["d"]) > 0:
clique_leader_output["description"] = eqid["d"]
if "t" in eqid and eqid["t"]:
clique_leader_output["taxa"] = eqid["t"]
if 'types' in eqid:
clique_leader_output["type"] = eqid['types'][-1]
clique_leaders_output.append(clique_leader_output)

CopilotAIFeb 25, 2026

Copy link

Choose a reason for hiding this comment

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

The loop structure here could be optimized. Currently, for every equivalent identifier, the code checks all conflation types to see if it's a clique leader. This could be improved by pre-computing a set of clique leaders for faster lookup, especially since the print statement on line 861 will execute for every single equivalent identifier in the response, which could be hundreds or thousands of times for large queries. Consider moving the clique leader check logic outside the main loop or optimizing it with a set-based lookup.

Copilot uses AI. Check for mistakes.
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
@gaurav
gaurav marked this pull request as draft February 25, 2026 01:48
@gauravgaurav mentioned this pull request Feb 25, 2026
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: In progress
Status: Backlog

Development

Successfully merging this pull request may close these issues.

Deconflation endpoint Add option to provide clique leaders in addition to the combined clique

2 participants

@gaurav
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

Add clique leaders option - #350

Draft
gaurav wants to merge 37 commits into
mainfrom
add-clique-leaders-option
Draft

Add clique leaders option#350
gaurav wants to merge 37 commits into
mainfrom
add-clique-leaders-option

Conversation

@gaurav

@gauravgaurav commented Dec 15, 2025

Copy link
Copy Markdown
Collaborator

This PR closes#320 by adding an include_clique_leaders option on normalization. This may be a way to fix#340. Also renames some variables and adds some LLM-generated function documentation.

This PR adds a new flag include_clique_leaders that can be set on both GET and POST /get_normalized_nodes endpoints. Activating this endpoint adds a clique_leaders key to each normalized identifier that includes a list of all the clique leaders in this clique, along with their name, type and taxa, and (if the appropriate flags are turned on) descriptions. This doesn't currently include all the identifiers in each clique, but that should be added without too much extra bother.

WIP

  • Would it be useful to include the list of identifiers for each clique leader? That will require some additional finagling with the code, but it shouldn't be too problematic.
  • Is clique_leaders really the best thing to call this thing? These are all clique leader identifiers, but maybe conflation_leaders or something else would be better?
  • Add tests to Babel Validator

Example

Example output for NCBIGene:1756 is included below. Note that the conflation type is included (e.g. "conflation": "GeneProtein") and that clique_leaders is a list of the cliques leaders ordered in their position in the normalization.

{
"NCBIGene:1756": {
"id": {
"identifier": "NCBIGene:1756",
"label": "DMD",
"description": "dystrophin"
},
"equivalent_identifiers": [
{
"identifier": "NCBIGene:1756",
"label": "DMD",
"description": "dystrophin",
"taxa": [
"NCBITaxon:9606"
],
"type": "biolink:Gene"
},
{
"identifier": "ENSEMBL:ENSG00000198947",
"type": "biolink:Gene"
},
{
"identifier": "HGNC:2928",
"label": "DMD",
"type": "biolink:Gene"
},
{
"identifier": "OMIM:300377",
"type": "biolink:Gene"
},
{
"identifier": "UMLS:C1414083",
"label": "DMD gene",
"type": "biolink:Gene"
},
{
"identifier": "UniProtKB:A0A087WV90",
"label": "A0A087WV90_HUMAN Dystrophin (trembl)",
"taxa": [
"NCBITaxon:9606"
],
"type": "biolink:Protein"
},
{
"identifier": "UniProtKB:A0A0S2Z3B5",
"label": "A0A0S2Z3B5_HUMAN Dystrophin isoform 2 (trembl)",
"taxa": [
"NCBITaxon:9606"
],
"type": "biolink:Protein"
},
{
"identifier": "UniProtKB:A0A0S2Z3J7",
"label": "A0A0S2Z3J7_HUMAN Dystrophin isoform 1 (Fragment) (trembl)",
"taxa": [
"NCBITaxon:9606"
],
"type": "biolink:Protein"
},
{
"identifier": "UniProtKB:A0A5H1ZRP9",
"label": "A0A5H1ZRP9_HUMAN Dystrophin (trembl)",
"taxa": [
"NCBITaxon:9606"
],
"type": "biolink:Protein"
},
{
"identifier": "UniProtKB:A0A5H1ZRQ1",
"label": "A0A5H1ZRQ1_HUMAN Dystrophin (trembl)",
"taxa": [
"NCBITaxon:9606"
],
"type": "biolink:Protein"
},
{
"identifier": "UniProtKB:A0A5H1ZRQ8",
"label": "A0A5H1ZRQ8_HUMAN Dystrophin (trembl)",
"taxa": [
"NCBITaxon:9606"
],
"type": "biolink:Protein"
},
{
"identifier": "UniProtKB:A0A5H1ZRR9",
"label": "A0A5H1ZRR9_HUMAN Dystrophin (trembl)",
"taxa": [
"NCBITaxon:9606"
],
"type": "biolink:Protein"
},
{
"identifier": "UniProtKB:A0A804HKY9",
"label": "A0A804HKY9_HUMAN Dystrophin (trembl)",
"taxa": [
"NCBITaxon:9606"
],
"type": "biolink:Protein"
},
{
"identifier": "UniProtKB:A7E212",
"label": "A7E212_HUMAN Dystrophin (trembl)",
"taxa": [
"NCBITaxon:9606"
],
"type": "biolink:Protein"
},
{
"identifier": "UniProtKB:P11532",
"label": "DMD_HUMAN Dystrophin (sprot)",
"taxa": [
"NCBITaxon:9606"
],
"type": "biolink:Protein"
},
{
"identifier": "PR:P11532",
"label": "dystrophin (human)",
"description": "A dystrophin that is encoded in the genome of human.",
"type": "biolink:Protein"
},
{
"identifier": "UMLS:C1437024",
"label": "DMD protein, human",
"type": "biolink:Protein"
},
{
"identifier": "MESH:C484258",
"label": "DMD protein, human",
"type": "biolink:Protein"
},
{
"identifier": "UniProtKB:Q16484",
"label": "Q16484_HUMAN DMD protein (Fragment) (trembl)",
"taxa": [
"NCBITaxon:9606"
],
"type": "biolink:Protein"
},
{
"identifier": "UniProtKB:Q4G0X0",
"label": "Q4G0X0_HUMAN DMD protein (trembl)",
"taxa": [
"NCBITaxon:9606"
],
"type": "biolink:Protein"
},
{
"identifier": "ENSEMBL:ENSP00000288447",
"type": "biolink:Protein"
},
{
"identifier": "ENSEMBL:ENSP00000288447.4",
"type": "biolink:Protein"
}
],
"descriptions": [
"dystrophin",
"A dystrophin that is encoded in the genome of human."
],
"taxa": [
"NCBITaxon:9606"
],
"clique_leaders": [
{
"identifier": "NCBIGene:1756",
"conflation": "GeneProtein",
"label": "DMD",
"description": [
"dystrophin"
],
"taxa": [
"NCBITaxon:9606"
],
"type": "biolink:Gene"
},
{
"identifier": "UniProtKB:A0A087WV90",
"conflation": "GeneProtein",
"label": "A0A087WV90_HUMAN Dystrophin (trembl)",
"taxa": [
"NCBITaxon:9606"
],
"type": "biolink:Protein"
},
{
"identifier": "UniProtKB:A0A0S2Z3B5",
"conflation": "GeneProtein",
"label": "A0A0S2Z3B5_HUMAN Dystrophin isoform 2 (trembl)",
"taxa": [
"NCBITaxon:9606"
],
"type": "biolink:Protein"
},
{
"identifier": "UniProtKB:A0A0S2Z3J7",
"conflation": "GeneProtein",
"label": "A0A0S2Z3J7_HUMAN Dystrophin isoform 1 (Fragment) (trembl)",
"taxa": [
"NCBITaxon:9606"
],
"type": "biolink:Protein"
},
{
"identifier": "UniProtKB:A0A5H1ZRP9",
"conflation": "GeneProtein",
"label": "A0A5H1ZRP9_HUMAN Dystrophin (trembl)",
"taxa": [
"NCBITaxon:9606"
],
"type": "biolink:Protein"
},
{
"identifier": "UniProtKB:A0A5H1ZRQ1",
"conflation": "GeneProtein",
"label": "A0A5H1ZRQ1_HUMAN Dystrophin (trembl)",
"taxa": [
"NCBITaxon:9606"
],
"type": "biolink:Protein"
},
{
"identifier": "UniProtKB:A0A5H1ZRQ8",
"conflation": "GeneProtein",
"label": "A0A5H1ZRQ8_HUMAN Dystrophin (trembl)",
"taxa": [
"NCBITaxon:9606"
],
"type": "biolink:Protein"
},
{
"identifier": "UniProtKB:A0A5H1ZRR9",
"conflation": "GeneProtein",
"label": "A0A5H1ZRR9_HUMAN Dystrophin (trembl)",
"taxa": [
"NCBITaxon:9606"
],
"type": "biolink:Protein"
},
{
"identifier": "UniProtKB:A0A804HKY9",
"conflation": "GeneProtein",
"label": "A0A804HKY9_HUMAN Dystrophin (trembl)",
"taxa": [
"NCBITaxon:9606"
],
"type": "biolink:Protein"
},
{
"identifier": "UniProtKB:A7E212",
"conflation": "GeneProtein",
"label": "A7E212_HUMAN Dystrophin (trembl)",
"taxa": [
"NCBITaxon:9606"
],
"type": "biolink:Protein"
},
{
"identifier": "UniProtKB:P11532",
"conflation": "GeneProtein",
"label": "DMD_HUMAN Dystrophin (sprot)",
"taxa": [
"NCBITaxon:9606"
],
"type": "biolink:Protein"
},
{
"identifier": "UniProtKB:Q16484",
"conflation": "GeneProtein",
"label": "Q16484_HUMAN DMD protein (Fragment) (trembl)",
"taxa": [
"NCBITaxon:9606"
],
"type": "biolink:Protein"
},
{
"identifier": "UniProtKB:Q4G0X0",
"conflation": "GeneProtein",
"label": "Q4G0X0_HUMAN DMD protein (trembl)",
"taxa": [
"NCBITaxon:9606"
],
"type": "biolink:Protein"
}
],
"type": [
"biolink:Gene",
"biolink:GeneOrGeneProduct",
"biolink:GenomicEntity",
"biolink:ChemicalEntityOrGeneOrGeneProduct",
"biolink:PhysicalEssence",
"biolink:OntologyClass",
"biolink:BiologicalEntity",
"biolink:ThingWithTaxon",
"biolink:NamedThing",
"biolink:PhysicalEssenceOrOccurrent",
"biolink:MacromolecularMachineMixin",
"biolink:Protein",
"biolink:GeneProductMixin",
"biolink:Polypeptide",
"biolink:ChemicalEntityOrProteinOrPolypeptide"
],
"information_content": 79.9
}
}

@gauravgaurav moved this from Backlog to In progress in Babel sprintsFeb 18, 2026
@gaurav
gaurav changed the base branch from master to add-nodenorm-version-to-statusFebruary 20, 2026 00:24
Base automatically changed from add-nodenorm-version-to-status to masterFebruary 20, 2026 00:31
@gaurav
gaurav marked this pull request as ready for review February 25, 2026 01:39
@gaurav
gaurav requested a review from CopilotFebruary 25, 2026 01:40

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This PR adds a new include_clique_leaders parameter to the /get_normalized_nodes endpoints (both GET and POST) to support deconflation use cases. When enabled, the API returns detailed information about individual clique leaders for conflated identifiers, helping users understand which cliques are being combined during gene/protein and drug/chemical conflation.

Changes:

  • Added include_clique_leaders boolean parameter to normalization endpoints
  • Modified normalization logic to collect and output clique leader information when requested
  • Updated several variable names for clarity (e.g., typestypes_with_ancestors)
  • Added LLM-generated docstrings to the get_eqids_and_types function

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 4 comments.

FileDescription
node_normalizer/server.pyAdded include_clique_leaders query parameter to GET endpoint and passed it through to normalization logic
node_normalizer/model/input.pyAdded include_clique_leaders field to CurieList input model for POST endpoint
node_normalizer/set_id.pyUpdated call to get_normalized_nodes() to explicitly pass include_clique_leaders=False
node_normalizer/normalizer.pyCore implementation: collects clique leaders when conflation is enabled, generates clique leader output with metadata (identifier, conflation type, label, description, taxa, type), and includes it in response
Comments suppressed due to low confidence (1)

node_normalizer/normalizer.py:558

  • The docstring for this function is incomplete and doesn't describe the parameters, including the new include_clique_leaders parameter. Given that the codebase uses docstring conventions (as seen in get_eqids_and_types and other functions), this function's docstring should be updated to document all parameters and their purposes, particularly the new optional parameters that control output formatting.
 """
Get value(s) for key(s) using redis MGET
"""

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment threadnode_normalizer/normalizer.py Outdated
Comment threadnode_normalizer/normalizer.py
Comment threadnode_normalizer/normalizer.py Outdated
Comment on lines +862 to +881
if clique_leaders:
for conflation_type in clique_leaders:
if canonical_id in clique_leaders[conflation_type] and eqid["i"] in clique_leaders[conflation_type][canonical_id]:
clique_leader_output = {
"identifier": eqid["i"],
"conflation": conflation_type,
}
if "label" in eq_item:
clique_leader_output["label"] = eq_item["label"]

# For description, taxa and type, we could read them from eq_item, but that
# is only set if the appropriate flag was turned on. For completeness, let's
# try picking them up if they've been passed to us at all.
if "d" in eqid and len(eqid["d"]) > 0:
clique_leader_output["description"] = eqid["d"]
if "t" in eqid and eqid["t"]:
clique_leader_output["taxa"] = eqid["t"]
if 'types' in eqid:
clique_leader_output["type"] = eqid['types'][-1]
clique_leaders_output.append(clique_leader_output)

CopilotAIFeb 25, 2026

Copy link

Choose a reason for hiding this comment

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

The loop structure here could be optimized. Currently, for every equivalent identifier, the code checks all conflation types to see if it's a clique leader. This could be improved by pre-computing a set of clique leaders for faster lookup, especially since the print statement on line 861 will execute for every single equivalent identifier in the response, which could be hundreds or thousands of times for large queries. Consider moving the clique leader check logic outside the main loop or optimizing it with a set-based lookup.

Copilot uses AI. Check for mistakes.
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
@gaurav
gaurav marked this pull request as draft February 25, 2026 01:48
@gauravgaurav mentioned this pull request Feb 25, 2026
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: In progress
Status: Backlog

Development

Successfully merging this pull request may close these issues.

Deconflation endpoint Add option to provide clique leaders in addition to the combined clique

2 participants

@gaurav