fix: filter GCFs left MIBiG-only after BGC attachment (#351) - #352
Open
vinvomero wants to merge 1 commit into
Open
fix: filter GCFs left MIBiG-only after BGC attachment (#351)#352vinvomero wants to merge 1 commit into
vinvomero wants to merge 1 commit into
Conversation
GCFs composed solely of MIBiG reference BGCs generate spurious Metcalf links to metabolite ions. The load-time MIBiG filter runs on raw `bgc_ids` before BGC objects are attached, so a GCF that loaded with a mix of antiSMASH and MIBiG ids but whose antiSMASH BGC was not loaded (e.g. no strain) is left with only its MIBiG BGC attached while `bgc_ids` still lists the missing id -- the id-based `has_mibig_only` cannot catch it. Add `GCF.has_mibig_only_bgcs()` (inspects the attached BGC objects) and a `drop_mibig_only_gcfs()` helper in genomics/utils.py that removes such GCFs and detaches their BGCs (leaving no stale `BGC.parents`). The loader applies it to `self.gcfs` after `get_mibig_from_gcf` (when MIBiG is in use), so `self.bgcs` / `self.mibig_strains_in_use` are unaffected -- only the scoring-facing GCF list changes. The fix is a no-op on datasets where every antiSMASH BGC has a strain (verified: tests/integration/test_nplinker_local.py counts unchanged); it only filters the pathological attachment-loss case, covered by unit tests including the shared-BGC invariant. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Fixes #351. Gene-cluster families (GCFs) composed solely of MIBiG reference BGCs produce spurious Metcalf links to metabolite ions. The existing MIBiG filter runs at load time on the raw
bgc_ids(viaGCF.has_mibig_only()) before BGC objects are attached, so a GCF that loaded with a mix of antiSMASH + MIBiG ids but whose antiSMASH BGC was not loaded is left with only its MIBiG BGC attached — whilebgc_idsstill lists the missing id, so the id-based check can't catch it. As @justinjjvanderhooft noted in #351, such GCFs should be filtered out.What this does
GCF.has_mibig_only_bgcs()— likehas_mibig_only()but inspecting the attachedbgcsobjects (viaBGC.is_mibig()), with an empty-set guard.drop_mibig_only_gcfs()ingenomics/utils.py(alongsideadd_bgc_to_gcf/get_mibig_from_gcf): removes such GCFs anddetach_bgc()s their BGCs, leaving no staleBGC.parentsback-reference.DatasetLoader._load_genomicsapplies it toself.gcfsafterget_mibig_from_gcf(when MIBiG is in use), soself.bgcs/self.mibig_strains_in_useare unchanged — only the scoring-facing GCF list is filtered.Tests
test_has_mibig_only_bgcs(empty / all-MIBiG / mixed).test_drop_mibig_only_gcfs— exercises the drop + detach directly, including a MIBiG BGC shared between a dropped and a kept GCF (the survivor keeps it; the back-reference points only to the survivor) and a no-op case.add_bgc_to_gcfshowing the old id-based check misses the leak while the new one catches it.The fix is a no-op on datasets where every antiSMASH BGC has a strain — verified:
tests/integration/test_nplinker_local.pycounts (390/64/46) are unchanged. It only filters the pathological attachment-loss case.Notes for reviewers
add_strain_to_bgc(the unmatched list is discarded, only an aggregate count logged). This PR filters the symptom the issue asks about; a follow-up could surface the strain-match loss (e.g. aWARNINGnaming the dropped BGC ids). Happy to do that separately.id.startswith("BGC")heuristic (BGC.is_mibig, already used repo-wide and documented as false-positive-prone). This PR escalates its consequence from mislabeling a BGC to dropping a GCF, so a real antiSMASH BGC whose id happens to start withBGCcould have its GCF dropped — rare, but a robust MIBiG provenance flag would be the durable fix.self.bgcs: a dropped GCF's MIBiG BGC stays inself.bgcswith an emptied.parents(soself.bgcsis identical to before this change). Harmless for scoring (the presence matrix is built fromself.gcfs), but an exported BGC can then reference no surviving GCF. I keptself.bgcsuntouched deliberately — happy to recompute it from the surviving GCFs instead if you prefer.docs/figure/data_loading_pipeline.svg; can add it if useful.🤖 Generated with Claude Code