kg_microbe.transform_utils.bacdive package
Submodules
kg_microbe.transform_utils.bacdive.bacdive module
BacDive KG transform.
Input: any file in data/raw/ (that was downloaded by placing a URL in incoming.txt/yaml and running run.py download.
Output: transformed data in data/raw/bacdive_strains.json:
Output these two files: - nodes.tsv - edges.tsv
- class kg_microbe.transform_utils.bacdive.bacdive.BacDiveTransform(input_dir=None, output_dir=None)
Bases:
TransformTemplate for how the transform class would be designed.
-
DATA_INPUTS:
tuple= ('mappings/isolation_source_to_ontology.tsv', 'mappings/kgmicrobe_unified_entity_mappings.sssom.tsv.gz') Repo-relative curation files this transform reads, beyond its own
data/raw/download.Declared so freshness tooling can tell that an output is stale against its data rather than only its code. Without it a mapping correction lands, every consumer keeps reporting FRESH, and a re-merge silently ships the old groundings: #778 corrected 16 isolation-source ids and #786 rewrote the unified chemical SSSOM, and the merged KG built afterwards still asserted 75 organisms isolated from a “Cell Line”, because nothing re-ran the transforms that read those files (#812).
Paths are relative to the repo root. Keep them tracked in git — the freshness check uses commit time, not mtime, because git checkout rewrites mtimes without changing content (#797).
List every curation file read, not a representative one. A partial declaration fails silently and looks identical to a complete one: ontologies_stubs declared 1 of the 11 files it read and was reported fresh after changes to the other ten (#839). Where the set comes from a constant, derive this from it rather than restating it.
-
TRANSFORM_INPUTS:
tuple= ('ontologies',) Reads
ontologies/ncbitaxon_nodes.tsvandontologies/chebi_nodes.tsvvia NCBITAXON_NODES_FILE / CHEBI_NODES_FILE. Undeclared until #1035: the path lives in constants.py, so the cross-transform guard never saw it.
- run(data_file=None, show_status=True)
Run the transformation.
-
DATA_INPUTS:
kg_microbe.transform_utils.bacdive.emission module
KGX row-emission helpers for the BacDive transform.
- kg_microbe.transform_utils.bacdive.emission.DEPOSIT_CONFLICT_HEADER = ['strain_id', 'parent_count', 'parents', 'bacdive_ids', 'resolution', 'asserted_parent']
Header of the deposit-claim report written alongside nodes.tsv / edges.tsv.
- kg_microbe.transform_utils.bacdive.emission.RESOLUTION_COLLAPSED = 'collapsed'
The claims sat on one lineage; the shared ancestor was asserted (#898).
- kg_microbe.transform_utils.bacdive.emission.RESOLUTION_SUPPRESSED = 'suppressed'
The claims were disjoint; no parent was asserted.
- kg_microbe.transform_utils.bacdive.emission.RESOLUTION_SUPPRESSED_NO_ANCESTRY = 'suppressed_ancestry_unavailable'
Ancestry for at least one claim could not be read, so the claims could not be compared and the deposit was suppressed as a precaution rather than a verdict. Distinguishing this matters – a degraded NCBITaxon adapter otherwise looks exactly like a data problem in BacDive (#897).
- class kg_microbe.transform_utils.bacdive.emission.StrainProvenanceWriter(inner_writer, *, knowledge_source, ks_column_index, publications_column_index)
Bases:
objectKeep PKS scalar and attach a BacDive record page to strain-derived evidence.
- writerow(row)
Write one row, augmenting bare source provenance when applicable.
- Return type:
None
- writerows(rows)
Apply provenance augmentation to a sequence of rows.
- Return type:
None
- kg_microbe.transform_utils.bacdive.emission.contested_deposit_description(parents)
Explain, on the node itself, why a contested deposit has no edges (#907).
A deposit whose claimants disagreed gets neither a parent nor a link to the records that cited it, which leaves an organism-typed node with a culture number for a label and nothing else – indistinguishable from an ingest gap. The description says which taxa were claimed so the emptiness reads as a decision.
Scoped to BacDive on purpose: 55 of these deposits are the object of an LPSN
close_matchedge, so a sentence claiming nothing links to the node would be false in the merged graph (#908). This transform cannot see LPSN’s output and should not try to – it states only what it did itself.- Parameters:
parents –
{NCBITaxon CURIE: [BacDive record key, ...]}for the deposit.- Returns:
One-sentence description naming the conflicting claims.
- kg_microbe.transform_utils.bacdive.emission.deposit_conflict_rows(contested)
Render contested deposit claims as report rows.
The report is the record that a claim existed and what became of it, so a consumer can recover the taxonomy that was suppressed, and see which deposits had theirs coarsened to a shared ancestor.
- Parameters:
contested –
contestedas returned byresolve_deposit_parents().- Returns:
List of rows matching
DEPOSIT_CONFLICT_HEADER.
- kg_microbe.transform_utils.bacdive.emission.entailed_by_every_claim(parents, ancestors_of)
Return the one claimed taxon that every other claim entails, or None.
Claims can differ without contradicting each other: one record records the species (
Brevundimonas vesicularis) and another the strain beneath it (Brevundimonas vesicularis NBRC 12165). The species claim is true either way, so it is the strongest statement all claimants support, and asserting it privileges neither record. Only a claim that was actually made is eligible – falling back to a computed common ancestor would put a taxon nobody claimed (often justBacteria) on the node.- Parameters:
parents – Iterable of claimed NCBITaxon CURIEs.
ancestors_of – Callable mapping a CURIE to its proper
is_aancestors, or None when no ontology is available.
- Returns:
The entailed CURIE, or None when the claims are disjoint.
- kg_microbe.transform_utils.bacdive.emission.resolution_asserts_a_parent(resolution)
Report whether a resolution left the deposit with a parent taxon.
Used to decide whether a record may be linked to the deposit at all. A deposit that got a parent is one identifier its claimants agree about, so linking to it is sound. One that got none is a designation two unrelated organisms happen to share, and
biolink:close_match– symmetric, and mapped toSEMMEDDB:same_as– would put those organisms two hops apart (#899).- Parameters:
resolution – One of the
RESOLUTION_*values.- Returns:
True when a parent was asserted.
- kg_microbe.transform_utils.bacdive.emission.resolve_deposit_parents(claims, ancestors_of=None, ancestry_failed=None)
Decide which culture-collection deposits may assert a parent taxon (#892).
A deposit number such as
ATCC 13722identifies a physical deposit, not a BacDive record, so several records can cite the same one. When they disagree about the taxon, emitting onesubclass_ofedge per claiming record leaves the deposit node with several parents and nothing to tell them apart, so a consumer that takes “the” parent gets whichever one file order put first.A parent is asserted when the claimants agree outright, and when they differ only in depth along one lineage – there the shared ancestor is asserted, per
entailed_by_every_claim(). Genuinely disjoint claims get no edge.Every deposit with more than one claim is reported, whichever way it went, so the report answers “what happened here and why” rather than listing only the half that lost its edge (#898).
- Parameters:
claims –
{strain CURIE: {NCBITaxon CURIE: [BacDive record key, ...]}}.ancestors_of – Callable mapping an NCBITaxon CURIE to its proper
is_aancestors. When None, any disagreement is treated as a conflict.ancestry_failed – Callable reporting whether a CURIE’s ancestry could not be read, used to mark a suppression that is a precaution rather than a verdict (#897). When None, no suppression is marked that way.
- Returns:
(resolved, contested).resolvedis a sorted list of(strain CURIE, NCBITaxon CURIE)pairs to emit.contestedis a sorted list of(strain CURIE, claims, resolution, asserted parent)for every deposit with more than one claim;asserted parentis empty when none was.
Module contents
BacDive transform.
- class kg_microbe.transform_utils.bacdive.BacDiveTransform(input_dir=None, output_dir=None)
Bases:
TransformTemplate for how the transform class would be designed.
-
DATA_INPUTS:
tuple= ('mappings/isolation_source_to_ontology.tsv', 'mappings/kgmicrobe_unified_entity_mappings.sssom.tsv.gz') Repo-relative curation files this transform reads, beyond its own
data/raw/download.Declared so freshness tooling can tell that an output is stale against its data rather than only its code. Without it a mapping correction lands, every consumer keeps reporting FRESH, and a re-merge silently ships the old groundings: #778 corrected 16 isolation-source ids and #786 rewrote the unified chemical SSSOM, and the merged KG built afterwards still asserted 75 organisms isolated from a “Cell Line”, because nothing re-ran the transforms that read those files (#812).
Paths are relative to the repo root. Keep them tracked in git — the freshness check uses commit time, not mtime, because git checkout rewrites mtimes without changing content (#797).
List every curation file read, not a representative one. A partial declaration fails silently and looks identical to a complete one: ontologies_stubs declared 1 of the 11 files it read and was reported fresh after changes to the other ten (#839). Where the set comes from a constant, derive this from it rather than restating it.
-
TRANSFORM_INPUTS:
tuple= ('ontologies',) Reads
ontologies/ncbitaxon_nodes.tsvandontologies/chebi_nodes.tsvvia NCBITAXON_NODES_FILE / CHEBI_NODES_FILE. Undeclared until #1035: the path lives in constants.py, so the cross-transform guard never saw it.
-
assay_edges_generated:
Optional[List]
-
assay_nodes_generated:
Optional[List]
-
assay_raw_data:
Optional[dict]
-
assay_target_nodes_generated:
Optional[List]
-
chebi_categories:
Dict[str,str]
-
isolation_source_mappings:
Dict[str,tuple]
-
ncbitaxon_fallback_cache:
Dict[str,Optional[str]]
-
ncbitaxon_labels:
Dict[str,str]
-
ncbitaxon_name_to_id:
Dict[str,str]
-
ncbitaxon_synonyms:
Dict[str,frozenset]
-
pathogenicity_mappings:
Dict[str,tuple]
-
phenotype_routing:
List[Dict[str,str]]
- run(data_file=None, show_status=True)
Run the transformation.
-
DATA_INPUTS: