2 #define BARRAY_PHYLO_H 1
12 #define MAKE_DUPL_VARS() \
13 bool DPL = Array.D_ptr()->duplication; \
14 size_t DATA_AT = data[0u];
16 #define IS_EITHER() (DATA_AT == Geese::etype_either)
17 #define IS_DUPLICATION() ((DATA_AT == Geese::etype_duplication) & (DPL))
18 #define IS_SPECIATION() ((DATA_AT == Geese::etype_speciation) & (!DPL))
20 #define IF_MATCHES() MAKE_DUPL_VARS() \
21 if (IS_EITHER() || IS_DUPLICATION() || IS_SPECIATION())
22 #define IF_NOTMATCHES() MAKE_DUPL_VARS() \
23 if (!IS_EITHER() && !IS_DUPLICATION() && !IS_SPECIATION())
36 #define PHYLO_RULE_LAMBDA(a) barry::Rule_fun_type<PhyloArray, PhyloRuleData> a = \
37 [](const PhyloArray & Array, size_t i, size_t j, PhyloRuleData & data)
39 #define PHYLO_COUNTER_LAMBDA(a) barry::Counter_fun_type<PhyloArray, PhyloCounterData> a = \
40 [](const PhyloArray & Array, size_t i, size_t j, PhyloCounterData & data)
42 #define PHYLO_RULE_DYN_LAMBDA(a) barry::Rule_fun_type<PhyloArray, PhyloRuleDynData> a = \
43 [](const PhyloArray & Array, size_t i, size_t j, PhyloRuleDynData & data)
45 #define PHYLO_CHECK_MISSING() if (Array.D_ptr() == nullptr) \
46 throw std::logic_error("The array data is nullptr."); \
48 inline std::string
get_last_name(
size_t d) {
return ((d == 1u)?
" at duplication" : ((d == 0u)?
" at speciation" :
""));}
81 return Array.D_ptr()->states[
i] ? 0.0 : 1.0;
86 tmp_count, tmp_init,
nullptr,
101 std::vector<size_t> nfun,
114 auto s = Array.D_ptr()->states[k];
119 for (
auto o = 0u; o < Array.ncol(); ++o)
121 if (Array(k, o) == 1u)
133 if (Array.D_ptr()->states[
i])
137 return (
i ==
data[1u]) ? 1.0 : 0.0;
145 tmp_count, tmp_init,
nullptr,
161 std::vector<size_t> nfun,
186 if (Array.D_ptr()->states[
i])
191 for (
size_t k = 0u; k < Array.ncol(); ++k)
194 if (Array(
i, k,
false) == 1u)
199 int diff =
static_cast<int>(
data[2u]) - counts + 1;
216 tmp_count, tmp_init,
nullptr,
218 std::to_string(k) +
" genes gain " + std::to_string(
i) +
247 for (
auto s : Array.D_ptr()->states)
252 return static_cast<double>(Array.ncol());
269 for (
size_t k = 0u; k < Array.nrow(); ++k)
273 if ((k !=
i) && (Array.D_ptr()->states[k] != (Array(k,
j,
false) == 1u)))
281 return Array.D_ptr()->states[
i] ? -1.0 : 1.0;
286 tmp_count, tmp_init,
nullptr,
318 if (Array.D_ptr()->states[
data[1u]] || Array.D_ptr()->states[
data[2u]])
321 double n =
static_cast<double>(Array.ncol());
322 return n * (n - 1.0) / 2.0;
334 auto nfunA =
data[1u];
335 auto nfunB =
data[2u];
337 if ((
i != nfunA) & (
i != nfunB))
340 if (Array.D_ptr()->states[
data[1u]] || Array.D_ptr()->states[
data[2u]])
343 size_t k = (
i == nfunA) ? nfunB : nfunA;
345 if (Array(k,
j) == 1u)
349 for (
auto off = 0u; off < Array.ncol(); ++off)
354 if ((Array(
i, off) == 0u) && (Array(k, off) == 0u))
364 tmp_count, tmp_init,
nullptr,
366 "Preserve pseudo gene (" +
367 std::to_string(nfunA) +
", " +
398 for (
auto s : Array.D_ptr()->states)
416 bool j_diverges =
false;
417 const std::vector< bool > & par_state = Array.D_ptr()->states;
419 for (
size_t f = 0u; f < Array.nrow(); ++f)
423 if (par_state[f] != (Array(f,
j) == 1u))
432 bool j_used_to_diverge =
false;
433 for (
size_t f = 0u; f < Array.nrow(); ++f)
440 j_used_to_diverge =
true;
447 if (par_state[f] != (Array(f,
j) == 1u))
449 j_used_to_diverge =
true;
458 if ((!j_used_to_diverge & !j_diverges) | (j_used_to_diverge & j_diverges))
462 return 1.0/Array.ncol();
465 return -1.0/Array.ncol();
470 tmp_count, tmp_init,
nullptr,
493 if (!Array.D_ptr()->states[
i])
510 for (
auto s : Array.D_ptr()->states)
514 return res *
static_cast<double>(Array.ncol());
519 tmp_count, tmp_init,
nullptr,
551 return static_cast<double>(Array.ncol());
563 int count = Array.colsum(
j);
567 if (count ==
static_cast<int>(
data[1u]))
571 if (count > ub && ((count - ub) == 1))
580 tmp_count, tmp_init,
nullptr,
582 "Genes with [" + std::to_string(lb) +
", " + std::to_string(ub) +
596 std::vector<size_t> nfun,
607 if (!Array.D_ptr()->states[
i])
610 return (
i ==
data[1u]) ? -1.0 : 0.0;
624 if (!Array.D_ptr()->states[f])
627 return static_cast<double>(Array.ncol());
633 tmp_count, tmp_init,
nullptr,
658 if (Array.D_ptr()->states[
i])
676 double noff =
static_cast<double> (Array.ncol());
678 for (
size_t k = 0u; k < Array.nrow(); ++k)
679 if (Array.D_ptr()->states[k])
689 tmp_count, tmp_init,
nullptr,
720 auto funA =
data[1u];
721 auto funB =
data[2u];
724 if ((funA !=
i) && (funB !=
i))
728 if (!Array.D_ptr()->states[funA] || !Array.D_ptr()->states[funB])
732 size_t other = (
i == funA)? funB : funA;
735 if (Array(other,
j,
false) == 1u)
738 for (
size_t off = 0u; off < Array.ncol(); ++off)
745 if ((Array(
i, off,
false) == 1u) && (Array(other, off,
false) == 0u))
752 for (
size_t off = 0u; off < Array.ncol(); ++off)
759 if ((Array(
i, off,
false) == 0u) && (Array(other, off,
false) == 1u))
779 tmp_count, tmp_init,
nullptr,
781 "Subfun between " + std::to_string(nfunA) +
" and " +
812 if ((
i != d1) && (
i != d2))
816 if (!Array.D_ptr()->states[d1] && !Array.D_ptr()->states[d2])
819 size_t other = (
i == d1)? d2 : d1;
821 if (Array(other,
j,
false) == 1u)
839 tmp_count, tmp_init,
nullptr,
841 "Co-gains " + std::to_string(nfunA) +
" & " + std::to_string(nfunB) +
864 std::vector< bool> is_longest(Array.ncol(),
false);
865 bool j_mutates =
false;
867 int nmutate_longest = 0;
869 auto states = Array.D_ptr()->states;
871 for (
auto off = 0u; off < Array.ncol(); ++off)
875 for (
auto & l :
data)
877 is_longest[off] =
true;
879 for (
auto f = 0u; f < Array.nrow(); ++f)
881 if ((Array(f, off) == 1u) != states[f])
886 if (is_longest[off] && (off !=
j))
905 if (std::fabs(nmutate - nmutate_longest) > 1)
909 bool j_mutates_prev =
false;
910 for (
auto f = 0u; f < Array.nrow(); ++f)
914 if ((f ==
i) && states[
i])
916 j_mutates_prev =
true;
919 else if ((Array(f,
j) == 1u) != states[f])
921 j_mutates_prev =
true;
928 auto nmutate_prev = nmutate;
929 auto nmutate_longest_prev = nmutate_longest;
930 if (j_mutates & !j_mutates_prev)
933 nmutate_longest_prev--;
937 else if (!j_mutates & j_mutates)
940 nmutate_longest_prev++;
948 ( ((nmutate == 0) & (nmutate_longest > 0)) ? 1.0 : 0.0 ) +
949 ( ((nmutate_prev == 0) & (nmutate_longest_prev > 0)) ? 1.0 : 0.0 );
958 if (Array.D_ptr()->blengths.size() != Array.ncol())
959 throw std::logic_error(
960 "longest should be initialized with a vec of size Array.ncol()."
964 size_t longest_idx = 0u;
966 data.reserve(Array.ncol());
968 for (
size_t ii = 1u; ii < Array.ncol(); ++ii)
971 diff = Array.D_ptr()->blengths[longest_idx] - Array.D_ptr()->blengths[ii];
982 else if (diff == 0.0)
987 data.shrink_to_fit();
989 if (
data.size() == 0u)
990 throw std::logic_error(
"The data on the longest branch has size 0.");
994 for (
size_t ii = 0u; ii < Array.nrow(); ++ii)
997 if (Array.D_ptr()->states[ii])
998 return (1.0 *
static_cast<double>(
data.size()));
1007 tmp_count, tmp_init,
nullptr,
1036 auto funA =
data[1u];
1037 auto funB =
data[2u];
1040 if ((
i != funA) && (
i != funB))
1044 size_t other = (
i == funA)? funB : funA;
1045 bool parent_i = Array.D_ptr()->states[
i];
1046 bool parent_other = Array.D_ptr()->states[other];
1048 if (!parent_i & !parent_other)
1050 else if (parent_i & parent_other)
1056 if (Array(other,
j) == 0u)
1060 for (
auto off = 0u; off < Array.ncol(); ++off)
1061 if ((Array(
i,off) == 0) && (Array(other,off) == 1))
1068 for (
auto off = 0u; off < Array.ncol(); ++off)
1069 if ((Array(
i,off) == 1) && (Array(other,off) == 0))
1086 tmp_count, tmp_init,
nullptr,
1088 "Neofun between " + std::to_string(nfunA) +
" and " +
1121 if (Array.D_ptr()->states[
i])
1126 for (
auto off = 0u; off < Array.ncol(); ++off)
1132 if ((Array(
i, off) == 0))
1151 tmp_count, tmp_init,
nullptr,
1153 "Pairwise neofun function " + std::to_string(nfunA) +
1181 const size_t & funA =
data[1u];
1182 const size_t & funB =
data[2u];
1185 if ((
i != funA) && (
i != funB))
1189 if (!Array.D_ptr()->states[funA] || Array.D_ptr()->states[funB])
1197 if (Array(funB,
j) == 0u)
1200 for (
auto off = 0u; off < Array.ncol(); ++off)
1206 if ((Array(funA, off) == 0u) && (Array(funB, off) == 1u))
1215 for (
auto off = 0u; off < Array.ncol(); ++off)
1221 if ((Array(funA, off) == 1u) && (Array(funB, off) == 0u))
1232 if (Array(funA,
j) == 0u)
1235 for (
auto off = 0u; off < Array.ncol(); ++off)
1241 if ((Array(funA, off) == 1u) && (Array(funB, off) == 0u))
1250 for (
auto off = 0u; off < Array.ncol(); ++off)
1256 if ((Array(funA, off) == 0u) && (Array(funB, off) == 1u))
1278 tmp_count, tmp_init,
nullptr,
1280 "Neofun from " + std::to_string(nfunA) +
" to " +
1313 const size_t funA =
data[1u];
1314 const size_t funB =
data[2u];
1317 if ((
i != funA) & (
i != funB))
1321 if ((!Array.D_ptr()->states[funA]) || Array.D_ptr()->states[funB])
1329 if (Array(funB,
j,
false) == 1u)
1334 for (
auto c = 0u; c < Array.ncol(); ++c)
1335 if ((c !=
j) && (Array(funA, c,
false) == 1u) && (Array(funB, c,
false) == 1u))
1344 if (Array(funA,
j,
false) == 0u)
1349 for (
auto c = 0u; c < Array.ncol(); ++c)
1350 if ((c !=
j) && (Array(funA, c,
false) == 1u))
1351 res += (Array(funB, c,
false) == 0u) ? 1.0 : -1.0;
1364 if (
data.size() != 3u)
1365 throw std::length_error(
"The counter data should be of length 2.");
1368 throw std::logic_error(
"Functions A and B should be different from each other.");
1370 if (
data[1u] >= Array.nrow())
1371 throw std::length_error(
"Function A in counter out of range.");
1373 if (
data[2u] >= Array.nrow())
1374 throw std::length_error(
"Function B in counter out of range.");
1381 tmp_count, tmp_init,
nullptr,
1383 "Coopt of " + std::to_string(nfunA) +
" by " +
1414 for (
auto s : Array.D_ptr()->states)
1416 return Array.ncol() ==
data[1u] ? 1.0 : 0.0;
1418 return data[1u] == 0 ? 1.0 : 0.0;
1431 bool j_diverges =
false;
1432 const auto & par_state = Array.D_ptr()->states;
1434 int k =
static_cast<int>(
data[1u]);
1436 for (
auto o = 0u; o < Array.ncol(); ++o)
1439 for (
auto f = 0u; f < Array.nrow(); ++f)
1443 if ((Array(f, o) == 1u) != par_state[f])
1460 if (std::abs(count - k) > 1)
1464 bool j_used_to_diverge =
false;
1465 for (
auto f = 0u; f < Array.nrow(); ++f)
1472 j_used_to_diverge =
true;
1479 if (par_state[f] != (Array(f,
j) == 1u))
1481 j_used_to_diverge =
true;
1489 auto count_prev = count;
1491 if ((!j_used_to_diverge & !j_diverges) | (j_used_to_diverge & j_diverges))
1494 else if (j_diverges)
1500 return (count == k ? 1.0 : 0.0) - (count_prev == k ? 1.0 : 0.0);
1505 tmp_count, tmp_init,
nullptr,
1507 std::to_string(k) +
" genes changing" +
get_last_name(duplication)
1532 for (
auto s : Array.D_ptr()->states)
1534 return data[1u] == 100 ? 1.0 : 0.0;
1551 bool j_diverges =
false;
1552 const std::vector< bool > & par_state = Array.D_ptr()->states;
1554 for (
size_t o = 0u; o < Array.ncol(); ++o)
1557 for (
size_t f = 0u; f < Array.nrow(); ++f)
1561 if ((Array(f, o) == 1u) != par_state[f])
1577 bool j_used_to_diverge =
false;
1578 for (
size_t f = 0u; f < Array.nrow(); ++f)
1585 j_used_to_diverge =
true;
1592 if (par_state[f] != (Array(f,
j) == 1u))
1594 j_used_to_diverge =
true;
1602 auto count_prev = count;
1604 if ((!j_used_to_diverge & !j_diverges) | (j_used_to_diverge & j_diverges))
1607 else if (j_diverges)
1613 double ncol =
static_cast<double>(Array.ncol());
1614 double p =
static_cast<double>(
data[1u]) / 100.0;
1616 return ((count/ncol) <= p ? 1.0 : 0.0) - ((count_prev/ncol) <= p ? 1.0 : 0.0);
1621 tmp_count, tmp_init,
nullptr,
1623 std::to_string(p) +
" prop genes changing" +
get_last_name(duplication)
1635 std::vector< size_t > nfun,
1647 for (
auto s : Array.D_ptr()->states)
1660 double res =
static_cast<double>(Array.ncol()) - 1.0;
1661 for (
auto off = 0u; off < Array.ncol(); ++off)
1666 if (Array(
i, off) == 1u)
1682 for (
auto&
i : nfun)
1684 tmp_count, tmp_init,
nullptr,
1686 "First gain " + std::to_string(
i) +
1712 for (
auto s : Array.D_ptr()->states)
1732 tmp_count, tmp_init,
nullptr,
1734 "Overall first gains" +
1759 size_t funpar = Array.D_ptr()->states[
i] == 1u;
1763 for (
auto off = 0u; off < Array.ncol(); ++off)
1768 if (funpar > Array(
i, off))
1770 else if (funpar < Array(
i, off))
1786 double n =
static_cast<double>(Array.ncol());
1787 for (
auto s : Array.D_ptr()->states)
1789 res += n * (n - 1.0) / 2.0;
1796 tmp_count, tmp_init,
nullptr,
1798 "Pairs of genes changing" +
1827 auto funA =
data[1u];
1828 auto funB =
data[2u];
1829 if ((funA !=
i) && (funB !=
i))
1832 size_t k = (funA ==
i) ? funB : funA;
1834 bool parent_i = Array.D_ptr()->states[
i];
1835 bool parent_k = Array.D_ptr()->states[k];
1842 if (!parent_i & !parent_k)
1845 if (Array(k,
j) == 1u)
1848 for (
auto off = 0u; off < Array.ncol(); ++off)
1854 if ((Array(
i, off) == 0u) && (Array(k, off) == 0u))
1860 else if (parent_i & !parent_k)
1863 if (Array(k,
j) == 1u)
1866 for (
auto off = 0u; off < Array.ncol(); ++off)
1872 if ((Array(
i, off) == 1u) && (Array(k, off) == 0u))
1878 else if (!parent_i & parent_k)
1881 if (Array(k,
j) == 0u)
1884 for (
auto off = 0u; off < Array.ncol(); ++off)
1890 if ((Array(
i, off) == 0u) && (Array(k, off) == 1u))
1899 if (Array(k,
j) == 0u)
1902 for (
auto off = 0u; off < Array.ncol(); ++off)
1908 if ((Array(
i, off) == 1u) && (Array(k, off) == 1u))
1926 double n =
static_cast< double >(Array.ncol());
1927 if (!Array.D_ptr()->states[
data[1u]] && !Array.D_ptr()->states[
data[2u]])
1928 return n * (n - 1.0) / 2.0;
1935 tmp_count, tmp_init,
nullptr,
1937 "Pariwise preserve (" + std::to_string(nfunA) +
", " +
1966 auto funA =
data[1u];
1967 auto funB =
data[2u];
1968 if ((funA !=
i) && (funB !=
i))
1971 size_t k = (funA ==
i) ? funB : funA;
1974 if (Array(k,
j) == 1)
1977 for (
auto off = 0u; off < Array.ncol(); ++off)
1982 if ((Array(
i,off) == 0u) && (Array(k,off) == 0u))
1990 for (
auto off = 0u; off < Array.ncol(); ++off)
1996 if ((Array(
i, off) == 1u))
2000 if (Array(k, off) == 0u)
2007 if (Array(k, off) == 1u)
2034 tmp_count, tmp_init,
nullptr,
2036 "First gain (either " + std::to_string(nfunA) +
" or " +
2058 if (Array.D().has_leaf)
2060 return Array(
i,
j) != 9u;
2066 support->get_rules()->add_rule(
2069 "Fix annotated leafs",
2070 "Reduces the support by fixing the cells of annotated leafs."
2099 size_t rule_type =
data.duplication;
2122 if (support->get_counters()->operator[](pos).data[0] != duplication)
2123 throw std::logic_error(
2124 "The rule is not compatible with the duplication type of the model." +
2125 std::string(
"The rule is for ") +
get_last_name(duplication) +
2127 support->get_counters()->operator[](pos).data[0]
2132 support->get_rules_dyn()->add_rule(
2135 support->get_current_stats(),
2136 pos, lb, ub, duplication
2138 std::string(
"Limiting changes in '") +
2139 support->get_counters()->get_names()[pos] +
2140 "' to [" + std::to_string(lb) +
", " +
2141 std::to_string(ub) + std::string(
"]") +
2143 std::string(
"When the support is ennumerated, the number of changes in '") +
2144 support->get_counters()->get_names()[pos] +
2145 std::to_string(pos) +
"' is limited to [" + std::to_string(lb) +
", " +
2146 std::to_string(ub) +
"]" +
2156 #undef MAKE_DUPL_VARS
2158 #undef IS_DUPLICATION
2159 #undef IS_SPECIATION
2161 #undef IF_NOTMATCHES
static const size_t etype_either
static const size_t etype_duplication
static const size_t etype_speciation
static const size_t etype_default
Data_Type &&counter_ data(std::move(counter_.data))
barry::Counters< PhyloArray, PhyloCounterData > PhyloCounters
std::vector< std::pair< size_t, size_t > > PhyloRuleData
barry::Support< PhyloArray, PhyloCounterData, PhyloRuleData, PhyloRuleDynData > PhyloSupport
void counter_overall_gains(PhyloCounters *counters, size_t duplication=Geese::etype_default)
Overall functional gains.
void counter_neofun_a2b(PhyloCounters *counters, size_t nfunA, size_t nfunB, size_t duplication=Geese::etype_default)
Total number of neofunctionalization events.
void counter_k_genes_changing(PhyloCounters *counters, size_t k, size_t duplication=Geese::etype_default)
Indicator function. Equals to one if genes changed and zero otherwise.
void counter_overall_changes(PhyloCounters *counters, size_t duplication=Geese::etype_default)
Total number of changes. Use this statistic to account for "preservation".
void counter_subfun(PhyloCounters *counters, size_t nfunA, size_t nfunB, size_t duplication=Geese::etype_default)
Total count of Sub-functionalization events.
void counter_genes_changing(PhyloCounters *counters, size_t duplication=Geese::etype_default)
Keeps track of how many genes are changing (either 0, 1, or 2 if dealing with regular trees....
void counter_co_opt(PhyloCounters *counters, size_t nfunA, size_t nfunB, size_t duplication=Geese::etype_default)
Function co-opting.
#define PHYLO_RULE_DYN_LAMBDA(a)
void counter_loss(PhyloCounters *counters, std::vector< size_t > nfun, size_t duplication=Geese::etype_default)
Total count of losses for an specific function.
#define PHYLO_CHECK_MISSING()
void counter_prop_genes_changing(PhyloCounters *counters, size_t duplication=Geese::etype_default)
Keeps track of how many genes are changing (either 0, 1, or 2 if dealing with regular trees....
void counter_gains(PhyloCounters *counters, std::vector< size_t > nfun, size_t duplication=Geese::etype_default)
Functional gains for a specific function (nfun).
void counter_pairwise_overall_change(PhyloCounters *counters, size_t duplication=Geese::etype_default)
Used when all the functions are in 0 (like the root node prob.)
void counter_gains_from_0(PhyloCounters *counters, std::vector< size_t > nfun, size_t duplication=Geese::etype_default)
Used when all the functions are in 0 (like the root node prob.)
void counter_overall_loss(PhyloCounters *counters, size_t duplication=Geese::etype_default)
Overall functional loss.
void counter_cogain(PhyloCounters *counters, size_t nfunA, size_t nfunB, size_t duplication=Geese::etype_default)
Co-evolution (joint gain or loss)
void counter_less_than_p_prop_genes_changing(PhyloCounters *counters, double p, size_t duplication=Geese::etype_default)
Indicator function. Equals to one if genes changed and zero otherwise.
void counter_pairwise_neofun_singlefun(PhyloCounters *counters, size_t nfunA, size_t duplication=Geese::etype_default)
Total number of neofunctionalization events sum_u sum_{w < u} [x(u,a)*(1 - x(w,a)) + (1 - x(u,...
void counter_preserve_pseudogene(PhyloCounters *counters, size_t nfunA, size_t nfunB, size_t duplication=Geese::etype_default)
Keeps track of how many pairs of genes preserve pseudostate.
void counter_pairwise_preserving(PhyloCounters *counters, size_t nfunA, size_t nfunB, size_t duplication=Geese::etype_default)
Used when all the functions are in 0 (like the root node prob.)
std::string get_last_name(size_t d)
void counter_overall_gains_from_0(PhyloCounters *counters, size_t duplication=Geese::etype_default)
Used when all the functions are in 0 (like the root node prob.)
void counter_longest(PhyloCounters *counters, size_t duplication=Geese::etype_default)
Longest branch mutates (either by gain or by loss)
void counter_gains_k_offspring(PhyloCounters *counters, std::vector< size_t > nfun, size_t k=1u, size_t duplication=Geese::etype_default)
k genes gain function nfun
#define PHYLO_COUNTER_LAMBDA(a)
#define PHYLO_RULE_LAMBDA(a)
Extension of a simple counter.
void counter_neofun(PhyloCounters *counters, size_t nfunA, size_t nfunB, size_t duplication=Geese::etype_default)
Total number of neofunctionalization events.
void counter_maxfuns(PhyloCounters *counters, size_t lb, size_t ub, size_t duplication=Geese::etype_default)
Cap the number of functions per gene.
void counter_pairwise_first_gain(PhyloCounters *counters, size_t nfunA, size_t nfunB, size_t duplication=Geese::etype_default)
Used when all the functions are in 0 (like the root node prob.)
void rule_dyn_limit_changes(PhyloSupport *support, size_t pos, size_t lb, size_t ub, size_t duplication=Geese::etype_default)
Overall functional gains.
void rule_leafs(PhyloSupport *support)