5#include <unordered_map>
47 if (d < 0)
err(
"in '%s': negative deme number detected.",__func__);
49 catch (
const std::invalid_argument& e) {
50 err(
"in '%s': invalid Newick format: deme should be indicated with an integer.",__func__);
52 catch (
const std::out_of_range& e) {
53 err(
"in '%s': invalid Newick format: deme out of range.",__func__);
55 catch (
const std::exception& e) {
56 err(
"in '%s': parsing deme label: %s.",__func__,e.what());
59 err(
"in '%s': other deme-parsing error.",__func__);
71 const std::unordered_map<string_t,color_t> options({
76 std::transform(copy.begin(),copy.end(),copy.begin(),
77 [](
unsigned char c){return std::tolower(c);});
79 col = options.at(copy);
81 catch (
const std::out_of_range& e) {
82 err(
"in %s: invalid metadata: type '%s' not recognized.",__func__,s.c_str());
91(string_t::const_iterator b,
92 string_t::const_iterator e)
97 if (std::regex_match(b,e,m,std::regex(
"^(?:\\[.*?\\])?([-+]?[0-9]*\\.?[0-9]+(?:[eE][-+]?[0-9]+)?)(?:\\[.*?\\])?$"))) {
99 bl = stod(m[1].str());
101 catch (
const std::invalid_argument& e) {
102 err(
"in '%s': invalid Newick format: branch length should be a non-negative decimal number.",__func__);
104 catch (
const std::out_of_range& e) {
105 err(
"in '%s': invalid Newick format: branch length out of range.",__func__);
107 catch (
const std::exception& e) {
108 err(
"in '%s': parsing branch-length: %s.",__func__,e.what());
111 err(
"in '%s': other branch-length parsing error.",__func__);
113 if (bl < 0.0)
err(
"in '%s': negative branch length detected.",__func__);
115 warn(
"in '%s': in branch-length spec '%s': no branch-length detected: assuming zero branch length.",__func__,string_t(b,e).c_str());
125(string_t::const_iterator b,
126 string_t::const_iterator e,
134 if (std::regex_match(b,e,m,std::regex(
"^.*?\\[&&PhyloPOMP.+?deme=(\\w+).*?\\].*$")))
136 if (std::regex_match(b,e,m,std::regex(
"^.*?\\[&&PhyloPOMP.+?type=(\\w+).*?\\].*$")))
159 string_t::const_reverse_iterator f = s.crend(), e = s.crbegin(), b = e;
161 int stack = 0, sqstack = 0;
162 if (!s.empty() && *b !=
';')
163 err(
"in '%s': invalid Newick format: no final semicolon.",__func__);
168 err(
"in '%s': invalid Newick: unbalanced parentheses.",__func__);
180 err(
"in '%s': 'type=extant' on internal node.",__func__);
181 tf = (q->slate > tf) ? q->slate : tf;
185 err(
"in '%s': invalid Newick: missing comma or semicolon.",__func__);
194 tf = (q->slate > tf) ? q->slate : tf;
205 err(
"in '%s': invalid Newick string: misplaced comma or unbalanced parentheses.",__func__);
208 tf = (q->slate > tf) ? q->slate : tf;
217 while (b != f && sqstack > 0) {
219 if (*b ==
']') sqstack++;
220 if (*b ==
'[') sqstack--;
223 err(
"in '%s': invalid Newick format: unbalanced square brackets.",__func__);
228 err(
"in '%s': invalid Newick: unbalanced square brackets.",__func__);
235 err(
"in '%s': invalid Newick format: misplaced colon.",__func__);
244 err(
"in '%s': invalid Newick format: unbalanced parentheses.",__func__);
247 tf = (q->slate > tf) ? q->slate : tf;
260 PROTECT(X = AS_CHARACTER(X));
261 PROTECT(T0 = AS_NUMERIC(T0));
262 PROTECT(Tf = AS_NUMERIC(Tf));
263 double t0 = *REAL(T0);
264 double tf = *REAL(Tf);
266 string_t x = CHAR(STRING_ELT(X,0));
Balls function as pointers.
size_t ndeme(void) const
number of demes
void clip_zlb(void)
clip out all zero-length branches
slate_t & timezero(void)
view/set zero time.
slate_t & time(void)
view/set current time.
genealogy_t & parse(const string_t &s)
Parse a Newick string and create the indicated genealogy.
node_t * make_node(name_t d=undeme)
void curtail(slate_t tnew, slate_t troot)
node_t * scan_branch_label(string_t::const_iterator b, string_t::const_iterator e, node_t *p, slate_t bl)
Encodes a genealogical node.
node_t * parent(void) const
name_t deme(void) const
view deme
ball_t * green_ball(void) const
pointer to my green ball
void insert(ball_t *a)
insert a ball into the pocket of a node
bool holds_own(void) const
void weed(void)
drop all dead roots
void sort(void)
order nodes in order of increasing time
void attach(node_t *p, node_t *q)
void swap(ball_t *a, ball_t *b)
swap balls a and b, wherever they lie
void trace_lineages(void)
ball_t * last_ball(void) const
retrieve the last ball
bool holds(ball_t *b) const
does this node hold the given ball?
SEXP serial(const TYPE &X)
binary serialization
static color_t scan_color(const std::string &s)
simple function for scanning the color
static slate_t scan_branch_length(string_t::const_iterator b, string_t::const_iterator e)
Scan the branch length.
static name_t scan_name(const string_t &s)
SEXP parse_newick(SEXP X, SEXP T0, SEXP Tf)