5#include <unordered_map>
29 bl = (s.empty()) ? 0.0 : stod(s);
31 catch (
const std::invalid_argument& e) {
32 err(
"in '%s': invalid Newick format: branch length should be a non-negative decimal number.",__func__);
34 catch (
const std::out_of_range& e) {
35 err(
"in '%s': invalid Newick format: branch length out of range.",__func__);
37 catch (
const std::exception& e) {
38 err(
"in '%s': parsing branch-length: %s.",__func__,e.what());
41 err(
"in '%s': other branch-length parsing error.",__func__);
43 if (bl < 0.0)
err(
"in '%s': negative branch length detected.",__func__);
57 if (d < 0)
err(
"in '%s': negative deme number detected.",__func__);
59 catch (
const std::invalid_argument& e) {
60 err(
"in '%s': invalid Newick format: deme should be indicated with an integer.",__func__);
62 catch (
const std::out_of_range& e) {
63 err(
"in '%s': invalid Newick format: deme out of range.",__func__);
65 catch (
const std::exception& e) {
66 err(
"in '%s': parsing deme label: %s.",__func__,e.what());
69 err(
"in '%s': other deme-parsing error.",__func__);
81 const std::unordered_map<string_t,color_t> options({
86 std::transform(copy.begin(),copy.end(),copy.begin(),
87 [](
unsigned char c){return std::tolower(c);});
89 col = options.at(copy);
91 catch (
const std::out_of_range& e) {
92 err(
"in %s: invalid metadata: type '%s' not recognized.",__func__,s.c_str());
101(string_t::const_iterator b,
102 string_t::const_iterator e)
109 if (std::regex_match(b,e,m,std::regex(
"^.*?\\[&&PhyloPOMP.+?deme=(\\w+).*?\\].*$")))
111 if (std::regex_match(b,e,m,std::regex(
"^.*?\\[&&PhyloPOMP.+?type=(\\w+).*?\\].*$")))
113 if (std::regex_match(b,e,m,std::regex(
"^.*:([-+]?[0-9]*\\.?[0-9]+(?:[eE][-+]?[0-9]+)?)$")))
116 warn(
"in '%s': in branch-string '%s': no branch-length detected: assuming zero branch length.",
117 __func__,string_t(b,e).c_str());
135 string_t::const_reverse_iterator b = s.crbegin(), e = b;
137 int stack = 0, sqstack = 0;
138 if (!s.empty() && *b !=
';')
139 err(
"in '%s': invalid Newick format: no final semicolon.",__func__);
140 while (b != s.crend()) {
144 err(
"in '%s': invalid Newick: unbalanced parentheses.",__func__);
156 err(
"in '%s': 'type=extant' on internal node.",__func__);
157 q->slate += p->
slate;
160 tf = (q->slate > tf) ? q->slate : tf;
164 err(
"in '%s': invalid Newick: missing comma or semicolon.",__func__);
174 q->slate += p->
slate;
177 tf = (q->slate > tf) ? q->slate : tf;
188 err(
"in '%s': invalid Newick string: misplaced comma or unbalanced parentheses.",__func__);
191 q->slate += p->
slate;
194 tf = (q->slate > tf) ? q->slate : tf;
203 while (b != s.crend() && sqstack > 0) {
205 if (*b ==
']') sqstack++;
206 if (*b ==
'[') sqstack--;
209 err(
"in '%s': invalid Newick format: unbalanced square brackets.",__func__);
210 if (b != s.crend()) b++;
218 err(
"in '%s': invalid Newick format: unbalanced parentheses.",__func__);
221 q->slate += p->
slate;
224 tf = (q->slate > tf) ? q->slate : tf;
237 PROTECT(X = AS_CHARACTER(X));
238 PROTECT(T0 = AS_NUMERIC(T0));
239 PROTECT(Tf = AS_NUMERIC(Tf));
240 double t0 = *REAL(T0);
241 double tf = *REAL(Tf);
243 string_t x = CHAR(STRING_ELT(X,0));
Balls function as pointers.
void drop_zlb(void)
drop all zero-length branches
size_t ndeme(void) const
number of demes
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(string_t::const_iterator b, string_t::const_iterator e)
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
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 name_t scan_name(const string_t &s)
SEXP parse_newick(SEXP X, SEXP T0, SEXP Tf)
static slate_t scan_slate(const string_t &s)