From ddc70cacbd5f48dda6c77ad8fa13ee2d44843cb1 Mon Sep 17 00:00:00 2001 From: peter Date: Wed, 14 Aug 2024 11:42:37 -0700 Subject: [PATCH] DFE parameter table; closes #1509 --- docs/_ext/speciescatalog.py | 117 ++++++++++++++++++++++++++++++++++++ 1 file changed, 117 insertions(+) diff --git a/docs/_ext/speciescatalog.py b/docs/_ext/speciescatalog.py index 99c5623f7..77da70b13 100644 --- a/docs/_ext/speciescatalog.py +++ b/docs/_ext/speciescatalog.py @@ -9,6 +9,7 @@ """ import csv import pathlib +import re from docutils import nodes from sphinx.util.docutils import SphinxDirective @@ -513,8 +514,124 @@ def dfe_section(self, species, dfe): section += nodes.paragraph(text=dfe.description) section += nodes.rubric(text="Citations") section += self.citation_list(dfe) + section += nodes.rubric(text="DFE parameters") + section += self.dfe_parameter_table(species, dfe) return [target, section] + def dfe_parameter_table(self, species, dfe): + table = nodes.table() + # proportion, distribution type, arguments, dominance + tgroup = nodes.tgroup(cols=4) + for _ in range(4): + colspec = nodes.colspec(colwidth=1) + tgroup.append(colspec) + + table += tgroup + + thead = nodes.thead() + tgroup += thead + row = nodes.row() + entry = nodes.entry() + entry += nodes.paragraph(text="Proportion of mutations") + row += entry + entry = nodes.entry() + entry += nodes.paragraph(text="Distribution type") + row += entry + entry = nodes.entry() + entry += nodes.paragraph(text="Parameters") + row += entry + entry = nodes.entry() + entry += nodes.paragraph(text="Dominance") + row += entry + thead.append(row) + + def parse_mutation_type(mt): + dt = mt.distribution_type + da = mt.distribution_args + if dt == "s": + # currently we only use this for rlnorm and unif + bits = re.split("[ ()*]", da[0]) + assert bits[0] == "return", "Unrecognized mutation type string" + if "rlnorm" in bits: + dt = "ln" if bits[1] == "-1" else "lp" + da = (float(bits[bits.index("rlnorm") + 2]), float(bits[-2])) + elif "runif" in bits: + dt = "u" + da = (float(bits[6]), float(bits[10])) + else: + raise ValueError("Unrecognized mutation type string") + + if dt == "f": + label = "Fixed s" + params = f"s = {da[0]:.3f}" + elif dt == "e": + label = "Exponential" + params = f"mean = {da[0]:.3f}" + elif dt == "g": + label = "Gamma" + params = f"mean = {da[0]:.3f}, " f"shape = {da[1]:.3f}" + elif dt == "n": + label = "Normal" + params = f"mean = {da[0]:.3f}, " f"sd = {da[1]:.3f}" + elif dt == "w": + label = "Weibull" + params = f"scale = {da[0]:.3f}, " f"shape = {da[1]:.3f}" + elif dt == "u": + label = "Uniform" + params = f"min = {da[0]:.3f}, " f"max = {da[1]:.3f}" + elif dt == "lp": + label = "Positive LogNormal" + params = f"meanlog = {da[0]:.3f}, " f"sdlog = {da[1]:.3f}" + elif dt == "ln": + label = "Negative LogNormal" + params = f"meanlog = {da[0]:.3f}, " f"sdlog = {da[1]:.3f}" + + if mt.dominance_coeff is None: + h_list = [] + for j in range(len(mt.dominance_coeff_list)): + slist = ( + ["-Inf"] + + [f"{s:.3f}" for s in mt.dominance_coeff_breaks] + + ["Inf"] + ) + if dt in ["e", "g", "w"]: + if da[0] < 0: + slist[0] = "0" + else: + slist[-1] = "0" + elif dt == "lp": + slist[0] = "0" + elif dt == "ln": + slist[-1] = "0" + mins = slist[j] + maxs = slist[j + 1] + h_list.append( + f"{mt.dominance_coeff_list[j]:.3f} on " f"[{mins}, " f"{maxs})" + ) + h = "h = " + "; ".join(h_list) + else: + h = f"h = {mt.dominance_coeff:.3f}" + return label, params, h + + rows = [] + for mt, prop in zip(dfe.mutation_types, dfe.proportions): + if prop > 0: + row = nodes.row() + rows.append(row) + entry = nodes.entry() + entry += nodes.paragraph(text=f"{100*prop:.1f}%") + row += entry + for label in parse_mutation_type(mt): + entry = nodes.entry() + entry += nodes.paragraph(text=label) + row += entry + + tbody = nodes.tbody() + tbody.extend(rows) + tgroup += tbody + + return table + def dfes_table(self, species): table = nodes.table() tgroup = nodes.tgroup(cols=3)