Source code for cocomico.score

"""
Compute scores for communities, which permit ranking communities based on potential
for cooperation or competition, or based on added value in terms of scope or activated
reactions.
"""

from functools import cache

from cocomico import constants as cx
from cocomico.base import Biomolecule, Exchange, Seeds
from cocomico.community import Community


[docs] @cache def competition(community: Community, seeds: Seeds) -> tuple[float, dict[str, float]]: """ The competition potential of a community is calculated as the ratio of polyopsonist metabolites to taxa. """ polyopsonist: dict[Biomolecule, int] = community.polyopsonist(seeds) num_taxa = len(community.taxa) score = float(sum(polyopsonist.values())) / num_taxa metrics = {cx.COMP: score, cx.COMP_NUM: len(polyopsonist)} return score, metrics
[docs] @cache def delta(community: Community, seeds: Seeds) -> tuple[float, dict[str, int]]: """ The delta score of a community is the difference between the number of metabolites in the community scope and the sum of the individual scopes. """ # Recall community.scope(seeds, choice): MetaboliteSet community_scope = len(community.scope(seeds)) individual_scope = sum( len(community.scope(seeds, choice=t)) for t in community.taxa ) score = community_scope - individual_scope metrics = { cx.DELTA: score, cx.DELTA_CSCOPE: community_scope, cx.DELTA_ISCOPE: individual_scope, } return score, metrics
[docs] @cache def rho(community: Community, seeds: Seeds) -> tuple[float, dict[str, int]]: """ The rho score of a community is the difference between the number of activated×taxon tuples in the community scope and the sum of the individual activated×taxon tuples. """ # Recall community.activated(seeds, choice): set[Reaction] # Recall Reaction = Tuple[str, Taxon] community_active = len(community.activated(seeds)) individual_active = sum( len(community.activated(seeds, choice=t)) for t in community.taxa ) score = community_active - individual_active metrics = { cx.RHO: score, cx.RHO_CACTIV: community_active, cx.RHO_IACTIV: individual_active, } return score, metrics
[docs] @cache def cooperation(community: Community, seeds: Seeds) -> tuple[float, dict[str, float]]: """ The cooperation potential of a community is calculated from the metabolic exchanges. It is the weighted sum, over all exchanged metabolites, of the number of producers and consumers of that metabolite. The weight is an exponentially decaying bonus. """ def weight(k: set) -> float: """Exponentially decaying weight, starting from 1, up to 2.""" n = len(k) return 2 - (0.5 ** (n - 1)) if n >= 1 else 0 # The value for each metabolite key is a set of (producer,consumer) pairs. exchanges: dict[Biomolecule, set[Exchange]] = community.exchange(seeds) prodcons = [ sum(weight({pc[which] for pc in pairs}) for pairs in exchanges.values()) for which in [0, 1] ] score = float(sum(prodcons)) metrics: dict[str, float] = { cx.COOP: score, cx.COOP_NUM: len(exchanges), cx.COOP_PROD: prodcons[0], cx.COOP_CONS: prodcons[1], } return score, metrics