# Cross-Repository Environmental Linking ## Overview CommunityMech supports two levels of cross-repository linking: 1. **Cultivation linking** (existing) -- `growth_media` connects communities to media actually used for cultivation, with `culturemech_id` and `media_ingredient_mech_id` on components. 2. **Environmental linking** (new) -- `related_media` and `related_ingredients` connect communities to CultureMech media and MediaIngredientMech ingredients that are *environmentally relevant*, even if not directly used for cultivation. This document covers the new environmental linking system. ## When to Use Which Field | Field | Class | Purpose | Example | |-------|-------|---------|---------| | `growth_media` | GrowthMedia | Media **actually used** for cultivation | "We grew the community in R2A medium" | | `related_media` | RelatedMedia | Media **environmentally relevant** to the community | "This peatland medium mimics the community's habitat" | | `growth_media.composition` | GrowthMediaComponent | Ingredients **in** a cultivation medium | "R2A contains 0.5 g/L yeast extract" | | `related_ingredients` | RelatedIngredient | Ingredients **relevant to the environment** | "Humic acid is the dominant organic matter in this peatland" | A medium can appear in both `growth_media` and `related_media`. The two fields serve different query patterns: cultivation history vs. environment-based discovery. ## Schema Classes ### MediaRelationshipEnum Describes how a medium relates to the community: | Value | Use When | |-------|----------| | `CULTIVATION_MEDIUM` | Medium was actually used to cultivate community members | | `ISOLATION_MEDIUM` | Medium was used for initial isolation from the environment | | `ENVIRONMENT_ANALOG` | Medium mimics the community's natural environment | | `REFERENCED_IN_STUDY` | Medium was referenced in a study of this community | | `SELECTIVE_ENRICHMENT` | Medium selectively enriches for specific functional groups | ### RelatedMedia Links a community to a CultureMech medium through environmental relevance. | Attribute | Required | Description | |-----------|----------|-------------| | `preferred_term` | Yes | Human-readable media name | | `culturemech_id` | No | CultureMech ID (format: `CultureMech:NNNNNN`) | | `relationship_type` | No | MediaRelationshipEnum value | | `shared_environment_term` | No | ENVO term linking community environment to medium | | `relevance_notes` | No | Why this medium is relevant | | `evidence` | No | Evidence items (multivalued) | ### RelatedIngredient Links a community to a MediaIngredientMech ingredient through environmental or metabolic relevance. | Attribute | Required | Description | |-----------|----------|-------------| | `preferred_term` | Yes | Human-readable ingredient name | | `mediaingredientmech_id` | No | MediaIngredientMech ID (format: `MediaIngredientMech:NNNNNN`) | | `chebi_term` | No | CHEBI ontology term for the compound | | `relevance` | No | Why this ingredient is relevant | | `evidence` | No | Evidence items (multivalued) | ## Cross-Repository ID Formats | Repository | Pattern | Example | |------------|---------|---------| | CommunityMech | `CommunityMech:NNNNNN` | `CommunityMech:000319` | | CultureMech | `CultureMech:NNNNNN` | `CultureMech:010001` | | MediaIngredientMech | `MediaIngredientMech:NNNNNN` | `MediaIngredientMech:000523` | IDs are validated by regex pattern. Cross-repository existence checks (verifying the ID exists in the partner repo) are optional and recommended as a periodic bulk validation step. ## Examples ### Minimal: Single Related Medium ```yaml id: CommunityMech:000050 name: Hot Spring Thermophile Community related_media: - preferred_term: Thermus Medium culturemech_id: CultureMech:003001 relationship_type: ENVIRONMENT_ANALOG ``` ### Full: SPRUCE Peatland Community ```yaml id: CommunityMech:000319 name: SPRUCE Peatland Warming Microbial Community ecological_state: STABLE community_origin: NATURAL community_category: METHANOGENESIS environment_term: preferred_term: peatland term: id: ENVO:00000044 label: peatland # Existing: media actually used for cultivation growth_media: - name: Anaerobic Basal Medium culturemech_id: CultureMech:005023 ph: "4.5" temperature: "25" atmosphere: ANAEROBIC # New: environmentally relevant media from CultureMech related_media: - preferred_term: Acidic Peatland Medium culturemech_id: CultureMech:010001 relationship_type: ENVIRONMENT_ANALOG shared_environment_term: id: ENVO:00000044 label: peatland relevance_notes: "Medium mimics acidic peatland conditions (pH 3.5-4.5)" evidence: - reference: PMID:38515239 supports: SUPPORT evidence_source: IN_VIVO snippet: "Peat microbial communities characterized from SPRUCE experimental plots" - preferred_term: Iron-Reducing Enrichment Medium culturemech_id: CultureMech:008012 relationship_type: SELECTIVE_ENRICHMENT relevance_notes: "Selective for iron-reducing bacteria detected in SPRUCE metagenomes" evidence: - reference: PMID:35481924 supports: SUPPORT evidence_source: COMPUTATIONAL snippet: "Geobacter-related MAGs enriched in deep peat with warming treatment" # New: environmentally relevant ingredients from MediaIngredientMech related_ingredients: - preferred_term: Humic acid mediaingredientmech_id: MediaIngredientMech:000523 chebi_term: id: CHEBI:34818 label: humic acid relevance: "Major peat organic matter component and electron acceptor" evidence: - reference: PMID:38515239 supports: SUPPORT evidence_source: IN_VIVO snippet: "Humic substances dominate dissolved organic matter in peat porewater" - preferred_term: Ferrous sulfate mediaingredientmech_id: MediaIngredientMech:000089 chebi_term: id: CHEBI:75832 label: iron(2+) sulfate relevance: "Iron source for iron-cycling bacteria in deeper peat layers" ``` ### All Relationship Types ```yaml related_media: - preferred_term: Vent Medium culturemech_id: CultureMech:007001 relationship_type: CULTIVATION_MEDIUM - preferred_term: Sulfide Isolation Agar culturemech_id: CultureMech:007015 relationship_type: ISOLATION_MEDIUM - preferred_term: Synthetic Hydrothermal Fluid culturemech_id: CultureMech:007020 relationship_type: ENVIRONMENT_ANALOG shared_environment_term: id: ENVO:01000030 label: hydrothermal vent - preferred_term: Marine Broth 2216 culturemech_id: CultureMech:000042 relationship_type: REFERENCED_IN_STUDY - preferred_term: Chitin Enrichment Medium culturemech_id: CultureMech:007030 relationship_type: SELECTIVE_ENRICHMENT ``` ## Cross-Repository Query Patterns ### SPARQL: Find Media for Peatland Communities ```sparql PREFIX cm: SELECT ?community_name ?media_name ?culturemech_id ?relationship WHERE { ?community cm:environment_term/cm:term/cm:id "ENVO:00000044" ; cm:name ?community_name ; cm:related_media ?rm . ?rm cm:preferred_term ?media_name ; cm:culturemech_id ?culturemech_id . OPTIONAL { ?rm cm:relationship_type ?relationship } } ``` ### SPARQL: Find Ingredients for an Environment ```sparql PREFIX cm: SELECT ?community_name ?ingredient ?mim_id ?relevance WHERE { ?community cm:environment_term/cm:term/cm:id "ENVO:00000044" ; cm:name ?community_name ; cm:related_ingredients ?ri . ?ri cm:preferred_term ?ingredient ; cm:mediaingredientmech_id ?mim_id . OPTIONAL { ?ri cm:relevance ?relevance } } ``` ### SPARQL: Full Cross-Repo Join via Shared ENVO Terms ```sparql PREFIX cm: PREFIX cult: PREFIX mim: SELECT ?community_name ?env_label ?media_name ?ingredient_name WHERE { ?community cm:name ?community_name ; cm:environment_term/cm:term/cm:id ?envo_id ; cm:environment_term/cm:term/cm:label ?env_label . ?media cult:source_environment/cult:term/cult:id ?envo_id ; cult:name ?media_name . ?ingredient mim:environmental_context/mim:term/mim:id ?envo_id ; mim:name ?ingredient_name . } ``` ### SPARQL: Reverse Lookup -- Communities for a CultureMech Medium ```sparql PREFIX cm: SELECT ?community_name ?environment ?relationship WHERE { ?community cm:related_media ?rm ; cm:name ?community_name ; cm:environment_term/cm:preferred_term ?environment . ?rm cm:culturemech_id "CultureMech:010001" ; cm:relationship_type ?relationship . } ``` ## Python Dataclass Usage ```python from communitymech.datamodel.communitymech import ( MicrobialCommunity, RelatedMedia, RelatedIngredient, MediaRelationshipEnum, Term, ) # Create a related medium rm = RelatedMedia( preferred_term="Acidic Peatland Medium", culturemech_id="CultureMech:010001", relationship_type=MediaRelationshipEnum.ENVIRONMENT_ANALOG, shared_environment_term=Term(id="ENVO:00000044", label="peatland"), relevance_notes="Mimics acidic peatland conditions", ) # Create a related ingredient ri = RelatedIngredient( preferred_term="Humic acid", mediaingredientmech_id="MediaIngredientMech:000523", chebi_term=Term(id="CHEBI:34818", label="humic acid"), relevance="Major peat organic matter component", ) # Add to a community community = MicrobialCommunity( id="CommunityMech:000319", name="SPRUCE Peatland Community", related_media=[rm], related_ingredients=[ri], ) ``` ## Backward Compatibility All new fields are optional: - Communities without `related_media` or `related_ingredients` remain valid - Existing `growth_media` and its `composition` are unchanged - No modifications to any existing classes or enums - Generated Python dataclasses default new fields to empty lists ## Validation ### Schema-level tests Run the cross-repo linking tests: ```bash cd CommunityMech PYTHONPATH=src python -m pytest tests/test_cross_repo_linking.py -v ``` Test data files are in `tests/data/test_cross_repo_linking/`: - `spruce_with_links.yaml` -- Full example with all features - `community_no_links.yaml` -- Backward compatibility - `community_all_relationship_types.yaml` -- All 5 enum values ### Cross-repo ID validator `just validate-cross-repo-ids FILE` checks that `culturemech_id` / `mediaingredientmech_id` values match their CURIE patterns and, when sibling-repo paths are configured, that the referenced IDs actually exist in those repos. ```bash # Pattern check only (no sibling-repo paths) just validate-cross-repo-ids kb/communities/SPRUCE_Peatland_Methane_Cycling_Community.yaml # Pattern + existence check COMMUNITYMECH_SIBLING_REPOS="CultureMech=../CultureMech/kb/media,MediaIngredientMech=../MediaIngredientMech/kb/ingredients" \ just validate-cross-repo-ids-all ``` The validator returns: - `error` for malformed CURIEs or IDs missing from a configured sibling repo - `info` for IDs whose existence check was skipped because the relevant sibling-repo path wasn't configured - nothing if a community has no cross-repo IDs at all Sibling-repo paths can also be passed via `--culturemech` / `--mediaingredientmech` flags to `scripts/validate_cross_repo_ids.py`. ## See Also - [Growth Media Linking](media_linking.md) -- Existing cultivation-based linking - Schema: `src/communitymech/schema/communitymech.yaml` - Dataclasses: `src/communitymech/datamodel/communitymech.py` - GitHub Issue: [CommunityMech#30](https://github.com/CultureBotAI/CommunityMech/issues/30)