Module abstochkin.het_calcs
Some functions for calculating metrics of population heterogeneity.
Expand source code
""" Some functions for calculating metrics of population heterogeneity. """
# Copyright (c) 2023, Alex Plakantonakis.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
from collections import Counter
from numpy import log, ndarray
from .process import MichaelisMentenProcess, RegulatedProcess, ReversibleProcess, \
RegulatedMichaelisMentenProcess, Process
def get_het_processes(processes: list[Process, ...]) -> list[Process, ...]:
"""
Filter the heterogeneous processes from a given list of processes.
A process is heterogeneous if any of its parameters are defined as such.
"""
het_procs = list()
for proc in processes:
if isinstance(proc, MichaelisMentenProcess):
if proc.is_heterogeneous or proc.is_heterogeneous_Km:
het_procs.append(proc)
elif isinstance(proc, RegulatedMichaelisMentenProcess):
if proc.is_heterogeneous or proc.is_heterogeneous_Km:
het_procs.append(proc)
else:
if isinstance(proc.regulating_species, list): # multiple regulators
if sum(proc.is_heterogeneous_K50) > 0:
het_procs.append(proc)
elif isinstance(proc.regulating_species, str): # only one regulator
if proc.is_heterogeneous_K50:
het_procs.append(proc)
elif isinstance(proc, RegulatedProcess):
if proc.is_heterogeneous:
het_procs.append(proc)
else:
if isinstance(proc.regulating_species, list): # multiple regulators
if sum(proc.is_heterogeneous_K50) > 0:
het_procs.append(proc)
elif isinstance(proc.regulating_species, str): # only one regulator
if proc.is_heterogeneous_K50:
het_procs.append(proc)
elif isinstance(proc, ReversibleProcess):
if proc.is_heterogeneous or proc.is_heterogeneous_rev:
het_procs.append(proc)
else: # isinstance(proc, Process)
if proc.is_heterogeneous:
het_procs.append(proc)
return het_procs
def richness(arr: list | ndarray) -> int:
"""
Calculate the species richness, or how many subspecies
a species population comprises.
"""
return len(Counter(arr))
def idx_het(arr: list | ndarray) -> float:
"""
Calculate the Index of Heterogeneity (ψ), defined as the probability
that two randomly chosen agents (without replacement) from a species
population belong to different subspecies.
- A homogeneous population returns 0.
- A heterogeneous population with two distinct subspecies of equal
fractional abundance (χ=0.5) *approaches* 0.5 as the population
size increases.
- A fully heterogeneous population returns 1.
"""
ck = Counter(arr) # counter of k values
n_tot = len(arr) # total number of entries in sequence `arr`
s = 0
for v in ck.values():
s += v * (v - 1)
try:
psi = 1 - s / (n_tot * (n_tot - 1))
except ZeroDivisionError:
psi = 0
return psi
def info_het(arr: list | ndarray) -> float:
"""
Information-theoretic measure of population heterogeneity.
- A homogeneous population returns 0.
- A heterogeneous population with two distinct subspecies of equal
fractional abundance (χ=0.5) returns ln(2). Note that this is
true regardless of the population size.
- For a fully heterogeneous population, the measure increases
with population size and has no upper limit.
"""
ck = Counter(arr) # counter of k values
n_tot = len(arr) # total number of agents
s = 0
for k, v in ck.items():
chi = v / n_tot
s -= chi * log(chi)
return s
Functions
def get_het_processes(processes: list[Process, ...]) ‑> list[Process, ...]
-
Filter the heterogeneous processes from a given list of processes. A process is heterogeneous if any of its parameters are defined as such.
Expand source code
def get_het_processes(processes: list[Process, ...]) -> list[Process, ...]: """ Filter the heterogeneous processes from a given list of processes. A process is heterogeneous if any of its parameters are defined as such. """ het_procs = list() for proc in processes: if isinstance(proc, MichaelisMentenProcess): if proc.is_heterogeneous or proc.is_heterogeneous_Km: het_procs.append(proc) elif isinstance(proc, RegulatedMichaelisMentenProcess): if proc.is_heterogeneous or proc.is_heterogeneous_Km: het_procs.append(proc) else: if isinstance(proc.regulating_species, list): # multiple regulators if sum(proc.is_heterogeneous_K50) > 0: het_procs.append(proc) elif isinstance(proc.regulating_species, str): # only one regulator if proc.is_heterogeneous_K50: het_procs.append(proc) elif isinstance(proc, RegulatedProcess): if proc.is_heterogeneous: het_procs.append(proc) else: if isinstance(proc.regulating_species, list): # multiple regulators if sum(proc.is_heterogeneous_K50) > 0: het_procs.append(proc) elif isinstance(proc.regulating_species, str): # only one regulator if proc.is_heterogeneous_K50: het_procs.append(proc) elif isinstance(proc, ReversibleProcess): if proc.is_heterogeneous or proc.is_heterogeneous_rev: het_procs.append(proc) else: # isinstance(proc, Process) if proc.is_heterogeneous: het_procs.append(proc) return het_procs
def idx_het(arr: list | numpy.ndarray) ‑> float
-
Calculate the Index of Heterogeneity (ψ), defined as the probability that two randomly chosen agents (without replacement) from a species population belong to different subspecies.
- A homogeneous population returns 0.
- A heterogeneous population with two distinct subspecies of equal fractional abundance (χ=0.5) approaches 0.5 as the population size increases.
- A fully heterogeneous population returns 1.
Expand source code
def idx_het(arr: list | ndarray) -> float: """ Calculate the Index of Heterogeneity (ψ), defined as the probability that two randomly chosen agents (without replacement) from a species population belong to different subspecies. - A homogeneous population returns 0. - A heterogeneous population with two distinct subspecies of equal fractional abundance (χ=0.5) *approaches* 0.5 as the population size increases. - A fully heterogeneous population returns 1. """ ck = Counter(arr) # counter of k values n_tot = len(arr) # total number of entries in sequence `arr` s = 0 for v in ck.values(): s += v * (v - 1) try: psi = 1 - s / (n_tot * (n_tot - 1)) except ZeroDivisionError: psi = 0 return psi
def info_het(arr: list | numpy.ndarray) ‑> float
-
Information-theoretic measure of population heterogeneity.
- A homogeneous population returns 0.
- A heterogeneous population with two distinct subspecies of equal fractional abundance (χ=0.5) returns ln(2). Note that this is true regardless of the population size.
- For a fully heterogeneous population, the measure increases with population size and has no upper limit.
Expand source code
def info_het(arr: list | ndarray) -> float: """ Information-theoretic measure of population heterogeneity. - A homogeneous population returns 0. - A heterogeneous population with two distinct subspecies of equal fractional abundance (χ=0.5) returns ln(2). Note that this is true regardless of the population size. - For a fully heterogeneous population, the measure increases with population size and has no upper limit. """ ck = Counter(arr) # counter of k values n_tot = len(arr) # total number of agents s = 0 for k, v in ck.items(): chi = v / n_tot s -= chi * log(chi) return s
def richness(arr: list | numpy.ndarray) ‑> int
-
Calculate the species richness, or how many subspecies a species population comprises.
Expand source code
def richness(arr: list | ndarray) -> int: """ Calculate the species richness, or how many subspecies a species population comprises. """ return len(Counter(arr))