Skip to content

Commit

Permalink
Start event series code/example/test
Browse files Browse the repository at this point in the history
  • Loading branch information
binho authored and binho committed Feb 20, 2024
1 parent 5288e45 commit e374153
Show file tree
Hide file tree
Showing 5 changed files with 167 additions and 16 deletions.
2 changes: 2 additions & 0 deletions examples/test_event_series.pj
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
trs <- read_tree(n=1, file_path="examples/trees_maps_files/geosse_dummy_tree2.tre", node_name_attr="index")
mapped_trs := map_attr(tree=trs, fun="smap", maps_file_path="examples/trees_maps_files/geosse_dummy_tree2_maps.tsv", tip_attr_file_path="examples/trees_maps_files/geosse_dummy_tree2_tip_states.tsv", attr_name="state", n_regions=2, geo="true")
1 change: 1 addition & 0 deletions examples/trees_maps_files/geosse_dummy_tree2.tre
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
((A:[&index=1]4.0,B:[&index=2]4.0):[&index=6]1.0,((C:[&index=3]1.0,D:[&index=4]1.0):[&index=7]2.0,E:[&index=5]3.0):[&index=8]2.0)[&index=9];
18 changes: 18 additions & 0 deletions examples/trees_maps_files/geosse_dummy_tree2_maps.tsv
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
iteration node_index branch_start_time branch_end_time start_state end_state transition_time transition_type parent_index child1_index child2_index
1 1 4 0 0 0 NA no_change 6 NA NA
1 2 4 0 1 1 NA no_change 6 NA NA
1 3 1 0 0 0 NA no_change 7 NA NA
1 4 1 0 1 1 NA no_change 7 NA NA
1 5 3 0 0 0 NA no_change 8 NA NA
1 6 5 4 0 2 4.75 anagenetic 9 1 2
1 6 4 4 2 2 NA no_change 9 1 2
1 6 4 4 2 0 4 cladogenetic 9 1 2
1 6 4 4 2 1 4 cladogenetic 9 1 2
1 7 3 1 1 2 2.75 anagenetic 8 3 4
1 7 1 1 2 2 NA no_change 8 3 4
1 7 1 1 2 0 1 cladogenetic 8 3 4
1 7 1 1 2 1 1 cladogenetic 8 3 4
1 8 5 3 0 2 3.25 anagenetic 9 5 7
1 8 3 3 2 2 NA no_change 9 5 7
1 8 3 3 2 0 4 cladogenetic 9 5 7
1 8 3 3 2 1 4 cladogenetic 9 5 7
5 changes: 5 additions & 0 deletions examples/trees_maps_files/geosse_dummy_tree2_tip_states.tsv
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
nd1 0
nd2 1
nd3 0
nd4 1
nd5 0
157 changes: 141 additions & 16 deletions src/phylojunction/functionality/stoch_map.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,9 @@
import sys
import os
import copy
import enum
import math
import numpy as np
import typing as ty
import matplotlib
import matplotlib.pyplot as plt # type: ignore
from abc import ABC, abstractmethod

# pj imports
import phylojunction.data.tree as pjt
Expand All @@ -20,13 +17,138 @@
__email__ = "[email protected]"


class StochMap():
class Hypothesis(enum.Enum):
VICARIANCE = 0
FOUNDER_EVENT = 1


class EvolRelevantEvent(ABC):
"""Evolution-relevant event.
Examples of evolution-relevant events are those represented by
stochastic maps (e.g., range contraction, range expansion,
extinction, dispersal) or the (paleogeographic) appearance and
disappearance of barriers.
Parameters:
n_chars (int): Number of characters involved in event.
age (float): Age of event (age of present moment is 0.0).
time (float, optional): Time of event (0.0 at origin or
root). Defaults to None.
"""

_n_chars: int
_age: float
_time: float

@abstractmethod
def __init__(self,
n_chars: int,
age: ty.Optional[float],
time: ty.Optional[float] = None) -> None:

self._n_chars = n_chars
self._age = age
self._time = time


@property
def age(self) -> float:
return self._age

@property
def time(self) -> float:
return self._time


class EvolRelevantEventSeries:
"""Series of evolution-relevant events.
This class has member methods that interrogate a series of event,
truncating it depending on what the user specifies.
"""

_event_list: ty.List[EvolRelevantEvent]
_n_events: int
_series_type: str
_trunc_event_list: ty.List[EvolRelevantEvent]
_trunc_n_events: int
_supported_hyp: Hypothesis

def __init__(self,
event_list: ty.List[EvolRelevantEvent],
series_type: str) -> None:

self._series_type = series_type

self.health_check()

self._event_list = event_list
self._n_events = len(event_list)

def health_check(self) -> None:
"""Confirm validity of event list given series type."""

if self._series_type == "speciation":
last_event = self._event_list[-1]

if not isinstance(last_event, RangeSplitOrBirth):
raise ec.SequenceInvalidLastError(type(last_event))

def truncate_upstream(self, truncator_fn: ty.Callable) -> None:
"""Deep-copy series and truncate copy upstream.
Truncation of an event series is done according to some
user-specified function. Truncation may be carried out, for
example, at the first event that destabilizes a range (i.e.,
the first "destabilizer" event).
Side-effects:
(i) Populate self._trunc_event_list
(ii) Populate self._trunc_n_events
Parameters:
truncator_fn (function): Method of static Truncate class
that executes truncation.
"""

self._trunc_event_list = truncator_fn(
copy.deepcopy(self._event_list))

self._trunc_n_events = len(self._trunc_event_list)


@property
def event_list(self) -> ty.List[EvolRelevantEvent]:
return self._event_list

@property
def n_events(self) -> int:
return self._n_events

@property
def series_type(self) -> str:
return self._series_type

@property
def supported_hyp(self) -> Hypothesis:
return self._supported_hyp

@supported_hyp.setter
def supported_hyp(self, a_hyp: Hypothesis) -> None:
if (a_hyp == Hypothesis.VICARIANCE or \
a_hyp == Hypothesis.FOUNDER_EVENT) and \
self._series_type != "speciation":
raise ec.SequenceHypothesisTypeError(a_hyp, self._series_type)

self._supported_hyp = a_hyp


class StochMap(EvolRelevantEvent):
"""Parent class for a single stochastic map.
Parameters:
n_chars (int): Number of characters (e.g., atomic regions).
age (float): Age of stochastic map (0.0 at present).
time (float): Time of stochastic map (0.0 at origin or root).
from_state (int): Integer representation of source state (i.e.,
source biogeographic range).
from_state_bit_patt (str): Bit pattern representation of
Expand All @@ -51,9 +173,6 @@ class StochMap():
focal node.
"""

n_chars: int
age: float
time: float
from_state: int
from_state_bit_patt: str
to_state: int
Expand All @@ -79,17 +198,17 @@ def __init__(self,
to_state2: ty.Optional[int] = None,
to_state2_bit_patt: ty.Optional[str] = None,
child2_node_name: ty.Optional[str] = None) -> None:

self.age = age
self.time = time

# initializing EvolRelevantEvent members
super().__init__(n_chars, age, time=time)

self.from_state = from_state
self.from_state_bit_patt = from_state_bit_patt
self.to_state = to_state
self.to_state_bit_patt = to_state_bit_patt
self.focal_node_name = focal_node_name
self.parent_node_name = parent_node_name
self.child_node_name = child_node_name
self.n_chars = n_chars

# if cladogenetic range split
self.child2_node_name = child2_node_name
Expand Down Expand Up @@ -1274,7 +1393,13 @@ def iter_mcmc_generations(self) -> ty.Iterator[StochMapsOnTree]:
yield self.stoch_maps_tree_dict[idx]


##################################
# Event series parsing functions #
##################################

def truncate_at_split_relevant_event(event_series: EvolRelevantEventSeries):
def _is_split_relevant_event():
pass


if __name__ == "__main__":
Expand Down Expand Up @@ -1325,7 +1450,7 @@ def iter_mcmc_generations(self) -> ty.Iterator[StochMapsOnTree]:
node_states_file_path="examples/trees_maps_files/geosse_dummy_tree1_tip_states.tsv",
stoch_map_attr_name="state")

fig = matplotlib.pyplot.figure()
fig = plt.figure()

ax = fig.add_axes([0.25, 0.2, 0.5, 0.6])
ax.patch.set_alpha(0.0)
Expand Down

0 comments on commit e374153

Please sign in to comment.