diff --git a/tsbrowse/pages/__init__.py b/tsbrowse/pages/__init__.py index 05493b1..9498c32 100644 --- a/tsbrowse/pages/__init__.py +++ b/tsbrowse/pages/__init__.py @@ -1,10 +1,7 @@ -from . import edge_explorer # noqa: F401 from . import edges # noqa: F401 -from . import frequency_spectra # noqa: F401 from . import mutations # noqa: F401 from . import nodes # noqa: F401 from . import overview # noqa: F401 -from . import popgen # noqa: F401 from . import tables # noqa: F401 from . import trees # noqa: F401 @@ -13,11 +10,8 @@ tables.TablesPage, mutations.MutationsPage, edges.EdgesPage, - edge_explorer.EdgeExplorerPage, trees.TreesPage, nodes.NodesPage, - popgen.PopgenPage, - frequency_spectra.FrequencySpectraPage, ] PAGES_MAP = {page.key: page for page in PAGES} PAGES_BY_TITLE = {page.title: page for page in PAGES} diff --git a/tsbrowse/pages/edge_explorer.py b/tsbrowse/pages/edge_explorer.py deleted file mode 100644 index 68272b2..0000000 --- a/tsbrowse/pages/edge_explorer.py +++ /dev/null @@ -1,52 +0,0 @@ -import bokeh.models as bkm -import holoviews as hv -import panel as pn - -from .. import config - - -class EdgeExplorerPage: - key = "edge-explorer" - title = "Edge Explorer" - - def __init__(self, tsm): - edges_df = tsm.edges_df - node_id_input = pn.widgets.TextInput(value="", name="Node ID") - edges_df["parent_time_right"] = edges_df["parent_time"] - tabulator = pn.widgets.Tabulator(show_index=False) - - def plot_data(node_id): - if len(node_id) > 0: - filtered_df = edges_df[edges_df["child"] == int(node_id)] - segments = hv.Segments( - filtered_df, - kdims=["left", "parent_time", "right", "parent_time_right"], - vdims=["child", "parent", "span", "branch_length"], - ) - hover_tool = bkm.HoverTool( - tooltips=[ - ("child", "@child"), - ("parent", "@parent"), - ("span", "@span"), - ("branch_length", "@branch_length"), - ] - ) - segments = segments.opts( - width=config.PLOT_WIDTH, - height=config.PLOT_HEIGHT, - tools=[hover_tool], - xlabel="Position", - ylabel="Time", - ) - - filtered_df = filtered_df.drop(columns=["parent_time_right"]) - tabulator.value = filtered_df - - return segments - else: - return pn.pane.Markdown("Please enter a Node ID.") - - dynamic_plot = pn.bind(plot_data, node_id=node_id_input) - - self.content = pn.Column(dynamic_plot, tabulator) - self.sidebar = pn.Column(pn.pane.Markdown("# Edge Explorer"), node_id_input) diff --git a/tsbrowse/pages/frequency_spectra.py b/tsbrowse/pages/frequency_spectra.py deleted file mode 100644 index 53520f5..0000000 --- a/tsbrowse/pages/frequency_spectra.py +++ /dev/null @@ -1,104 +0,0 @@ -import holoviews as hv -import numpy as np -import pandas as pd -import panel as pn - -from .. import config - - -def make_afs_df(ts, span_normalise, afs_type, mode): - polarised = afs_type == "folded" - - afs = ts.allele_frequency_spectrum( - span_normalise=span_normalise, windows=None, polarised=polarised, mode=mode - ) - num_samples = ts.num_samples - afs_df = pd.DataFrame( - { - "allele_count": np.arange(1, num_samples + 1), - "num_sites": afs[1:], - } - ) - return afs_df - - -def make_afs_panel(afs_df, log_bins, mode): - len_df = len(afs_df) - if log_bins: - max_order = int(np.ceil(np.log10(len_df))) - bin_edges = np.geomspace(1, 10**max_order, num=max_order + 1).astype(int) - xrotation = 0 - else: - num_bins = min(20, int(np.sqrt(len_df))) - bin_edges = np.linspace(1, len_df, num_bins).astype(int) - xrotation = 45 - - labels = [f"{bin_edges[i]} - {bin_edges[i + 1]}" for i in range(len(bin_edges) - 1)] - afs_df["bins"] = pd.cut( - afs_df["allele_count"], - bins=bin_edges, - right=True, - include_lowest=True, - labels=labels, - ) - - summed_values = pd.DataFrame( - afs_df.groupby("bins", observed=True)["num_sites"].sum().reset_index() - ) - summed_values.columns = ["bins", "ac_sum"] - - afs_bar = hv.Bars(summed_values, kdims="bins", vdims="ac_sum").opts( - height=config.PLOT_HEIGHT, - responsive=True, - xlabel="Allele count", - ylabel="Number of sites", - xrotation=xrotation, - tools=["hover"], - title=f"{mode} mode", - bar_width=1, - shared_axes=False, - ) - return afs_bar - - -class FrequencySpectraPage: - key = "sfs" - title = "SFS" - - def __init__(self, tsm): - log_bins_chk = pn.widgets.Checkbox(name="log-scale bins", value=True) - span_normalise_chk = pn.widgets.Checkbox(name="span normalise", value=False) - afs_type_radio = pn.widgets.RadioButtonGroup( - name="SFS type", options=["folded", "unfolded"], value="folded" - ) - plot_options = pn.Column( - pn.pane.Markdown("# Frequency Spectra"), - pn.Row(pn.Column(log_bins_chk, span_normalise_chk), afs_type_radio), - ) - - afs_site_df = pn.bind( - make_afs_df, tsm.ts, span_normalise_chk, afs_type_radio, "site" - ) - afs_site_bar = pn.bind( - make_afs_panel, afs_df=afs_site_df, log_bins=log_bins_chk, mode="site" - ) - afs_branch_df = pn.bind( - make_afs_df, tsm.ts, span_normalise_chk, afs_type_radio, "branch" - ) - afs_branch_bar = pn.bind( - make_afs_panel, afs_df=afs_branch_df, log_bins=log_bins_chk, mode="branch" - ) - - site_count_table = pn.widgets.Tabulator( - afs_site_df, show_index=False, disabled=True, layout="fit_data_stretch" - ) - branch_count_table = pn.widgets.Tabulator( - afs_branch_df, show_index=False, disabled=True, layout="fit_data_stretch" - ) - layout = pn.Row( - pn.Column(afs_site_bar, site_count_table), - pn.Column(afs_branch_bar, branch_count_table), - ) - - self.content = pn.Column(layout, sizing_mode="stretch_width") - self.sidebar = plot_options diff --git a/tsbrowse/pages/popgen.py b/tsbrowse/pages/popgen.py deleted file mode 100644 index 5385f96..0000000 --- a/tsbrowse/pages/popgen.py +++ /dev/null @@ -1,80 +0,0 @@ -import holoviews as hv -import numpy as np -import panel as pn -from holoviews import opts - - -def make_one_way_stats(ts, windows_trees, windows_count, span_normalise, statistic): - windows_count = windows_count - if windows_trees: - windows = "trees" - x_axis = ts.breakpoints(as_array=True)[:-1] - else: - windows = np.concatenate( - ( - np.arange( - 0, ts.sequence_length, max(1, ts.sequence_length // windows_count) - ), - [ts.sequence_length], - ) - ) - x_axis = windows[:-1] - - if statistic == "Diversity": - site_statistic = ts.diversity( - span_normalise=span_normalise, windows=windows, mode="site" - ) - branch_statistic = ts.diversity( - span_normalise=span_normalise, windows=windows, mode="branch" - ) - else: - site_statistic = ts.segregating_sites( - span_normalise=span_normalise, windows=windows, mode="site" - ) - branch_statistic = ts.segregating_sites( - span_normalise=span_normalise, windows=windows, mode="branch" - ) - - ratio = np.divide(branch_statistic, site_statistic, where=(site_statistic != 0)) - modes = {"Site": site_statistic, "Branch": branch_statistic, "Branch/Site": ratio} - stat_curves = [ - hv.Curve((x_axis, v), "Genomic position", k).opts(interpolation="steps-post") - for k, v in modes.items() - ] - - layout = hv.Layout(stat_curves).cols(1) - layout.opts(opts.Curve(height=200, responsive=True)) - return layout - - -class PopgenPage: - key = "popgen" - title = "Pop Gen" - - def __init__(self, tsm): - ts = tsm.ts - windows_trees = pn.widgets.Checkbox(name="Tree-based windows", value=False) - windows_count = pn.widgets.IntSlider( - name="Window count", start=1, end=100_000, value=1000 - ) - span_normalise = pn.widgets.Checkbox(name="Span normalise", value=True) - stat_radiobox = pn.widgets.RadioButtonGroup( - name="Statistic", - options=["Diversity", "Segregating Sites"], - value="Segregating Sites", - ) - plot_options = pn.Column( - pn.Row(pn.Column(windows_trees, span_normalise), stat_radiobox), - windows_count, - ) - one_way_panel = pn.bind( - make_one_way_stats, - ts=ts, - windows_trees=windows_trees, - windows_count=windows_count, - span_normalise=span_normalise, - statistic=stat_radiobox, - ) - windows_trees.jslink(windows_count, value="disabled") - self.content = pn.Column(one_way_panel) - self.sidebar = pn.Column(pn.pane.Markdown("# Pop Gen"), plot_options)