#######################################################
# Code for checking the ana_events table, which
# is sometimes a table, and sometimes NA
#######################################################
example_ana_events_table <- function()
{
example_code='
ana_events_table = NA
check_for_ana_events_table(ana_events_table)
ana_events_table = NaN
check_for_ana_events_table(ana_events_table)
ana_events_table = c(NA, NaN, NA)
check_for_ana_events_table(ana_events_table)
ana_events_table = example_ana_events_table()
check_for_ana_events_table(ana_events_table)
'
# Just to have an example BSM ana_events_table, for checks
# from dput(ana_events_table)
# Load the structure
ana_events_table = structure(list(node = c(19L, 23L, 25L, 32L, 32L, 36L), ord_ndname = c(19L,
23L, 25L, 32L, 32L, 36L), node_lvl = c(2, 3, 5, 4, 4, 1), node.type = c("tip",
"internal", "internal", "internal", "internal", "internal"),
parent_br = c(20L, 31L, 25L, 27L, 27L, 36L), edge.length = c(2.827918756,
1.689170274, 0.3347375986, 0.4601084855, 0.4601084855, 2.372081244
), ancestor = c(36L, 22L, 24L, 31L, 31L, 20L), daughter_nds = list(
`19` = integer(0), `23` = c(24L, 30L), `25` = c(26L,
29L), `32` = c(33L, 13L), `32` = c(33L, 13L), `36` = c(37L,
19L)), node_ht = c(5.2, 2.7110008382, 3.3480878148, 2.2148560087,
2.2148560087, 2.372081244), time_bp = c(0, 2.4889992, 1.8519122,
2.985144, 2.985144, 2.8279188), fossils = c(FALSE, NA, NA,
NA, NA, NA), label = c("P_hexandra_Oahu", "inNode23", "inNode25",
"inNode32", "inNode32", "inNode36"), tipnames = c("P_hexandra_Oahu",
"P_fauriei2,P_greenwelliae07,P_greenwelliae907,P_hathewayi_1,P_hawaiiensis_WaikamoiL1,P_kaduana_HawaiiLoa,P_kaduana_PuuKukuiAS,P_mauiensis_Eke,P_mauiensis_PepeAS",
"P_fauriei2,P_hathewayi_1,P_hawaiiensis_WaikamoiL1,P_kaduana_PuuKukuiAS,P_mauiensis_Eke,P_mauiensis_PepeAS",
"P_hawaiiensis_Makaopuhi,P_mariniana_Kokee2,P_mariniana_MauiNui,P_mariniana_Oahu",
"P_hawaiiensis_Makaopuhi,P_mariniana_Kokee2,P_mariniana_MauiNui,P_mariniana_Oahu",
"P_hexandra_K1,P_hexandra_M,P_hexandra_Oahu"), sampled_states_AT_nodes = c(3L,
6L, 9L, 16L, 16L, 6L), sampled_states_AT_brbots = c(6, 2,
3, 7, 7, 2), left_desc_nodes = c(NA, 24L, 26L, 33L, 33L,
37L), right_desc_nodes = c(NA, 30L, 29L, 13L, 13L, 19L),
samp_LEFT_dcorner = c(NA, 3, 9, 15, 15, 2), samp_RIGHT_dcorner = c(NA,
2, 4, 2, 2, 6), clado_event_type = c("", "vicariance (v)",
"subset (s)", "vicariance (v)", "vicariance (v)", "subset (s)"
), clado_event_txt = c("", "KO->O,K", "OM->OM,M", "KOMH->OMH,K",
"KOMH->OMH,K", "KO->K,KO"), clado_dispersal_to = c("", "",
"", "", "", ""), nodenum_at_top_of_branch = c(19, 23, 25,
32, 32, 36), trynum = c(21, 7, 84, 293, 293, 19), brlen = c(2.827918756,
1.689170274, 0.3347375986, 0.4601084855, 0.4601084855, 2.372081244
), current_rangenum_1based = c(6, 2, 3, 7, 14, 2), new_rangenum_1based = c(3,
6, 9, 14, 16, 6), current_rangetxt = c("KO", "K", "O", "KM",
"KMH", "K"), new_rangetxt = c("O", "KO", "OM", "KMH", "KOMH",
"KO"), abs_event_time = c(2.69243630957946, 2.83491980803861,
2.15629285978422, 3.05739740782267, 3.01228826742977, 4.59435041439648
), event_time = c(0.135482446420536, 1.34324966596139, 0.0303569388157761,
0.38785507767733, 0.432964218070227, 0.605649629603522),
event_type = c("e", "d", "d", "d", "d", "d"), event_txt = c("KO->O",
"K->KO", "O->OM", "KM->KMH", "KMH->KOMH", "K->KO"), new_area_num_1based = c(NA,
2, 3, 4, 2, 2), lost_area_num_1based = c("1", "-", "-", "-",
"-", "-"), dispersal_to = c("-", "O", "M", "H", "O", "O"),
extirpation_from = c("K", "-", "-", "-", "-", "-")), class = "data.frame", row.names = c("19",
"23", "25", "32", "321", "36"))
return(ana_events_table)
} # END example_ana_events_table <- function()
check_for_ana_events_table <- function(ana_events_table)
{
example_code='
ana_events_table = NA
check_for_ana_events_table(ana_events_table)
ana_events_table = NaN
check_for_ana_events_table(ana_events_table)
ana_events_table = c(NA, NaN, NA)
check_for_ana_events_table(ana_events_table)
ana_events_table = example_ana_events_table()
check_for_ana_events_table(ana_events_table)
'
ana_events_table_TF = FALSE
if (class(ana_events_table) == "data.frame")
{
ana_events_table_TF = TRUE
# Check for table, but with no rows
if (dim(ana_events_table)[1] == 0)
{
ana_events_table_TF = FALSE
txt = paste0("STOP ERROR in check_for_ana_events_table(): the ana_events_table is of class 'data.frame', but has 0 rows. Printing to screen:")
cat("\n")
cat(txt)
cat("\n")
cat("\nana_events_table:\n")
print(ana_events_table)
stop(txt)
}
###############################################
# Check for NAs on each row
###############################################
all_NA_rows = rep(FALSE, times=nrow(ana_events_table))
for (i in 1:length(all_NA_rows))
{
NA_TF = is.na(c(unlist(ana_events_table[i,])))
nan_TF = is.nan(c(unlist(ana_events_table[i,])))
TF = (NA_TF + nan_TF) > 0
if (sum(TF) == length(TF))
all_NA_rows[i] = TRUE
}
if (any(all_NA_rows == TRUE) == TRUE)
{
ana_events_table_TF = FALSE
error_msg = "STOP ERROR in check_for_ana_events_table(): your anagenetic events table seems to have row(s) that have all NAs. This could be due to an out of date 'BioGeoBEARS_stochastic_mapping_v1.R' file, missing this bug fix: '# NJM 2016-05-05 bug fix: add 'as.numeric' rownums_in_trtable = as.numeric(tmptable_rows$nodenum_at_top_of_branch)'.\nPrinting 'ana_events_table' to screen:"
cat("\n")
cat(error_msg)
cat("\n")
cat("\nana_events_table:\n")
print(ana_events_table)
cat("\n")
stop(error_msg)
}
return(ana_events_table_TF) # Return TRUE, yes it's a data.frame
} # END if (class(ana_events_table) == "data.frame")
if (is.null(ana_events_table) == TRUE)
{
ana_events_table_TF = FALSE
txt = paste0("STOP WARNING in check_for_ana_events_table(): the ana_events_table is NOT of class 'data.frame', but is NULL.")
return(ana_events_table_TF)
}
# It's not a data.frame; what is it?
if (length(ana_events_table) > 1)
{
ana_events_table_TF = FALSE
txt = paste0("STOP WARNING in check_for_ana_events_table(): the ana_events_table is NOT of class 'data.frame', but is longer than a single element. Printing to screen:")
cat("\n")
cat(txt)
cat("\n")
cat("\nana_events_table:\n")
print(ana_events_table)
stop(txt)
}
# It's not a data.frame; what is it?
if (length(ana_events_table) == 0)
{
ana_events_table_TF = FALSE
txt = paste0("STOP WARNING in check_for_ana_events_table(): the ana_events_table is NOT of class 'data.frame', but has length ZERO. Printing to screen:")
cat("\n")
cat(txt)
cat("\n")
cat("\nana_events_table:\n")
print(ana_events_table)
stop(txt)
}
# It's not a data.frame; what is it?
NA_TF = is.na(ana_events_table)
nan_TF = is.nan(ana_events_table)
TF = (NA_TF + nan_TF) > 0
if (TF == TRUE)
{
ana_events_table_TF = FALSE
return(ana_events_table_TF)
}
return(ana_events_table_TF)
} # END check_for_ana_events_table <- function(ana_events_table)
#######################################################
# Stochastic mapping on a non-stratified analysis
#######################################################
#
# This function does stochastic mapping on non-stratified analysis, or
# calls stochastic_mapping_on_stratified() if the input is stratified.
#
# stochastic_mapping_inputs = get_inputs_for_stochastic_mapping_from_results_object(res=resDEC)
# stochastic_mapping_results = stochastic_map_given_inputs(stochastic_mapping_inputs)
#
# For stochastic mapping on stratified analysis:
#
# stochastic_mapping_inputs_list = get_inputs_for_stochastic_mapping_stratified(res=resDEC)
# stochastic_mapping_results = stochastic_mapping_on_stratified(res=resDEC, stochastic_mapping_inputs_list=stochastic_mapping_inputs_list)
#
stochastic_map_given_inputs <- function(stochastic_mapping_inputs, piecenum=NULL, maxtries=40000, seedval=as.numeric(Sys.time()), include_null_range, master_nodenum_toPrint=0, allow_null_tips=FALSE)
{
#######################################################
# running_stochastic_mapping, given a results object
#######################################################
defaults='
res
rootedge=FALSE
statenum_bottom_root_branch_1based=NULL
printlevel=1
stratified=FALSE
min_branchlength=0.000001
stochastic_mapping_inputs=stochastic_mapping_inputs_list
piecenum=NULL
maxtries=40000
seedval=12346
include_null_range=TRUE
'
# Fix allow_null_tips
if (isblank_TF(allow_null_tips) == TRUE)
{
allow_null_tips = FALSE
}
# Set the seed
#print(paste0("stochastic_map_given_inputs seedval=", seedval, sep=""))
if (seedval > 2147483647)
{
seedval = seedval %% 2147483647
}
set.seed(seedval)
# Necessary setting to avoid getting numbers etc. in the stochastic mapping output
options(stringsAsFactors=FALSE)
# Load inputs
rootedge = stochastic_mapping_inputs$rootedge
statenum_bottom_root_branch_1based = stochastic_mapping_inputs$statenum_bottom_root_branch_1based
printlevel = stochastic_mapping_inputs$printlevel
stratified = stochastic_mapping_inputs$stratified
if (is.null(stratified) == TRUE)
{
stop("ERROR in stochastic_map_given_inputs(); stochastic_mapping_inputs$stratified is NULL")
}
min_branchlength = stochastic_mapping_inputs$min_branchlength
cluster_already_open = stochastic_mapping_inputs$cluster_already_open
res = stochastic_mapping_inputs$res
Qmat = stochastic_mapping_inputs$Qmat
COO_weights_columnar = stochastic_mapping_inputs$COO_weights_columnar
Rsp_rowsums = stochastic_mapping_inputs$Rsp_rowsums
tipranges = stochastic_mapping_inputs$tipranges
areas = stochastic_mapping_inputs$areas
state_indices_0based = stochastic_mapping_inputs$state_indices_0based
states_list = state_indices_0based
ranges_list = stochastic_mapping_inputs$ranges_list
numstates = stochastic_mapping_inputs$numstates
if (include_null_range == TRUE)
{
numstates_during_cladogenesis = numstates - 1
} else {
numstates_during_cladogenesis = numstates - 0
}
if (stratified == FALSE)
{
trtable = stochastic_mapping_inputs$trtable
tr = stochastic_mapping_inputs$tr
phy2 = stochastic_mapping_inputs$phy2
independent_likelihoods_on_each_branch = stochastic_mapping_inputs$independent_likelihoods_on_each_branch
} else {
subtable_rowsTF = stochastic_mapping_inputs$master_table_timeperiod_i$piecenum == piecenum
subtable_rownums = (1:nrow(stochastic_mapping_inputs$master_table_timeperiod_i))[subtable_rowsTF]
# Convert master_table_timeperiod_i to trtable
trtable = stochastic_mapping_inputs$master_table_timeperiod_i[subtable_rownums,]
# trtable parts to use/change are ONLY the parts corresponding to this particular treepiece
#trtable_rows_correct_pieces_TF = trtable_all_pieces$piecenum == piecenum
#trtable = trtable_all_pieces[trtable_rows_correct_pieces_TF,]
independent_likelihoods_on_each_branch = stochastic_mapping_inputs$independent_likelihoods_by_tree_piece_for_timeperiod_i[[piecenum]]
phy = stochastic_mapping_inputs$tree_sections_list$return_pieces_list[[piecenum]]
phy2 = reorder(phy, "pruningwise") # Do this,
} # END if (stratified == FALSE)
# Basic tree info
ntips = length(phy2$tip.label)
num_internal_nodes = phy2$Nnode
tipnums = 1:ntips
root_nodenum = ntips+1
nodenums = root_nodenum:(ntips+num_internal_nodes)
if (stratified == FALSE)
{
# Add a column for the sampled node states
sampled_states_AT_nodes = rep(NA, nrow(trtable))
sampled_states_AT_brbots = rep(NA, nrow(trtable))
# Add the right and left descendant node numbers
leftright_nodes_matrix = get_leftright_nodes_matrix_from_results(phy2)
left_desc_nodes = rep(NA, nrow(trtable))
right_desc_nodes = rep(NA, nrow(trtable))
# dcorner = descendant corner (i.e. right after speciation)
samp_LEFT_dcorner = rep(NA, nrow(trtable))
samp_RIGHT_dcorner = rep(NA, nrow(trtable))
# Events on branches
anagenetic_events_txt_below_node = rep(NA, nrow(trtable))
trtable = cbind(trtable, sampled_states_AT_nodes, sampled_states_AT_brbots, left_desc_nodes, right_desc_nodes, samp_LEFT_dcorner, samp_RIGHT_dcorner, anagenetic_events_txt_below_node)
# This works, the reverse does not -- 2015-04-06
# (LR for tree plots is opposite for the internal structure)
# NJMtest: should be right, then left
trtable$left_desc_nodes[nodenums] = leftright_nodes_matrix$right
trtable$right_desc_nodes[nodenums] = leftright_nodes_matrix$left
trtable[nodenums,]
} else {
# Stratified analysis:
# You've already got all these columns
junk = 1
} # END if (stratified == FALSE)
#returned_mats1 = get_Qmat_COOmat_from_BioGeoBEARS_run_object(default_BioGeoBEARS_run_object)
#returned_mats1
# returned_mats2 = get_Qmat_COOmat_from_res(res)
# returned_mats2
#
# # Extract output
# Qmat = returned_mats2$Qmat
# COO_weights_columnar = returned_mats2$COO_weights_columnar
# Rsp_rowsums = returned_mats2$Rsp_rowsums
# Calculate the likelihood P((left_state,right_state)|anc_state)
# for each scenario (unconstrained)
# Note:
# COO_weights_columnar indices are 0-based, with no null_range
# So, add 2 to get it so that e.g. state 0 = state 2 = Kauai
#
# Or, add 1 to get the 1based state indexes INSIDE COO_weights_columnar
#
# COO_weights_columnar =
# ancestral index, left index, right index, conditional
# probability given ancestral states. (assuming likelihood
# of descendants is 1)
# Probabilities of each range-inheritance scenario, conditional
# on ancestral state (without constraints on Left Branch state)
#like_LeftRight_given_AncState = COO_weights_columnar[[4]] / (Rsp_rowsums[1+COO_weights_columnar[[1]]])
#like_LeftRight_given_AncState
# Calculate the total number of range-inheritance scenarios
# under the model
# (this is the number of scenarios with weight > 0)
# (weight per event/ sum(weights) = prob. per event)
num_scenarios = length(COO_weights_columnar[[1]])
#######################################################
#######################################################
# THIS IS AN UPPASS FROM THE TIPS TO THE ROOT
#######################################################
#######################################################
# Check to make sure you have the necessary inputs
if (exists("COO_weights_columnar") == FALSE)
{
stop("\nERROR_A: calc_loglike_sp requires 'COO_weights_columnar', 'Rsp_rowsums', and cppSpMethod==3 for marginal ancestral state estimations.\n")
}
if (exists("Rsp_rowsums") == FALSE)
{
stop("\nERROR_B: calc_loglike_sp requires 'COO_weights_columnar', 'Rsp_rowsums', and cppSpMethod==3 for marginal ancestral state estimations.\n")
}
##########################################################
# 1. Sample a state at the root of the tree or subtree (if it doesn't exist)
# 2. Given the root state, calculate uppass probabilities to the corners
# 3. Multiply the corner uppass probs by the downpass probs
#
##########################################################
# This is for sampling just the root node state
# If there is no rootedge, and if the starting state
# at the root node is not determined
# If stratified analysis, no root edge, no pre-determined root state
TF1 = ((stratified == TRUE) && (rootedge == FALSE) && (is.na(trtable$sampled_states_AT_nodes[root_nodenum])) && (trtable$node.type[root_nodenum] == "root"))
# If non-stratified analysis, whether or not there is a root edge, no pre-determined root state
#TF2 = ((stratified == FALSE) && (is.na(trtable$sampled_states_AT_nodes[root_nodenum])) && (trtable$node.type[root_nodenum] == "root"))
TF2 = (stratified == FALSE)
#print(TF2)
if ( TF1 || TF2 )
{
# Sample a state at the global root
# The global root nodenum will be different than the subtree root nodenum
if (stratified == TRUE)
{
global_rootTF = trtable$node.type == "root"
# Error check
if (sum(global_rootTF) != 1)
{
stop("\n\nStop ERROR: no global root node in subtree.\n\n")
}
global_root_nodenum = trtable$node[global_rootTF]
} else {
global_root_nodenum = root_nodenum
} # END if (stratified == TRUE)
# Get the stateprobs at the global root, and sample from them
probs_branch_top = res$ML_marginal_prob_each_state_at_branch_top_AT_node[global_root_nodenum,]
statenums = 1:numstates
statenum_1based = sample(x=statenums, size=1, replace=TRUE, prob=probs_branch_top)
statenum_1based
#print(global_root_nodenum)
#print(round(node_stateprobs,3))
#print(statenum_1based)
# Store the sampled state at the root
trtable$sampled_states_AT_nodes[root_nodenum] = statenum_1based
}
# If stratified analysis, with root edge, no pre-determined root state
# Simulate up the root branch, if that exists
# (and if its a stratified analysis)
#print(stratified)
if ( (stratified == TRUE) && (rootedge == TRUE))
{
# Find the downpass conditional likelihoods (normalized) that have
# been pre-calculated
#res$condlikes
#res$inputs$master_table
subtable_rootTF = trtable$SUBnode.type == "root"
subtable_rownum = (1:nrow(trtable))[subtable_rootTF]
TF1 = res$inputs$master_table$node == trtable$node[subtable_rownum]
TF2 = res$inputs$master_table$stratum == trtable$stratum[subtable_rownum]
TF3 = res$inputs$master_table$piecenum == trtable$piecenum[subtable_rownum]
TF4 = res$inputs$master_table$piececlass == "subtree"
TF5 = res$inputs$master_table$SUBnode.type == "root"
TF = (TF1 + TF2 + TF3 + TF4 + TF5) == 5
rownums = 1:nrow(res$inputs$master_table)
rownum = rownums[TF]
rownum
downpass_condlikes_at_branch_top = res$condlikes[rownum,]
downpass_relprobs_at_branch_top = downpass_condlikes_at_branch_top / sum(downpass_condlikes_at_branch_top)
# Now you just need to exponentiate up, given the previous-done
# independent likelihoods
starting_state_1based = trtable$sampled_states_AT_brbots[root_nodenum]
condprobs_branch_top = rep(0, times=numstates)
condprobs_branch_bot = rep(0, times=numstates)
condprobs_branch_bot[starting_state_1based] = 1
# 2017-04-06_error check
if (sum(condprobs_branch_bot) == 0)
{
txt = "STOP ERROR BB2: sum(condprobs_branch_bot) == 0. Printing starting_state_1based of condprobs_branch_bot[starting_state_1based] = 1:"
cat("\n\n")
print(txt)
print("print(starting_state_1based):")
print(starting_state_1based)
cat("\n\n")
stop(txt)
}
# Exponentiate up (well, sorta, exponential pre-calculated)
#condprobs_branch_top = condprobs_branch_bot %*% independent_likelihoods_by_tree_piece_for_timeperiod_i[[piecenum]]
branch_length = trtable$SUBedge.length[root_nodenum]
if (stochastic_mapping_inputs$store_stratum_states_list_TF == FALSE)
{
independent_likelihoods_on_root_branch_of_subtree = expokit_dgpadm_Qmat2(times=branch_length, Qmat=Qmat, transpose_needed=TRUE)
# NJMtest: tried FALSE, still issue
}
if (stochastic_mapping_inputs$store_stratum_states_list_TF == TRUE)
{
subset_nums = (1:length(stochastic_mapping_inputs$states_allowed_this_timeperiod_TF))[stochastic_mapping_inputs$states_allowed_this_timeperiod_TF]
# Expand the subset Qmat to be full-size
Qmat_big = matrix(data=0, nrow=length(stochastic_mapping_inputs$states_allowed_this_timeperiod_TF), ncol=length(stochastic_mapping_inputs$states_allowed_this_timeperiod_TF))
Qmat_big[subset_nums,subset_nums] = Qmat
independent_likelihoods_on_root_branch_of_subtree = expokit_dgpadm_Qmat2(times=branch_length, Qmat=Qmat_big, transpose_needed=TRUE)
# NJMtest: tried FALSE, still issue
}
# NJMtest: reversing, no effect
# NJMtest: transpose, no effect
# print("condprobs_branch_bot")
# print(condprobs_branch_bot)
# print("independent_likelihoods_on_root_branch_of_subtree")
# print(independent_likelihoods_on_root_branch_of_subtree)
condprobs_branch_bot %*% independent_likelihoods_on_root_branch_of_subtree
condprobs_branch_top = condprobs_branch_bot %*% independent_likelihoods_on_root_branch_of_subtree
# 2021-06-22_NJM allow null tips means, possibly, sister groups with null ranges
# (at least, Michael Nicolai has this)
dont_zero_out_nulls = TRUE
if ((include_null_range == TRUE) && (allow_null_tips == FALSE) && (dont_zero_out_nulls==TRUE))
{
condprobs_branch_top[1] = 0 # zero out the NULL range, since it is impossible in a survivor
downpass_relprobs_at_branch_top[1] = 0
}
# State probabilities at the top of the branch
probs_branch_top = condprobs_branch_top * downpass_relprobs_at_branch_top
probs_branch_top = probs_branch_top / sum(probs_branch_top)
master_nodenum = res$inputs$master_table$node[rownum]
if (master_nodenum == master_nodenum_toPrint)
{
print("stochastic_map_given_inputs():")
print("rownum:")
print(rownum)
print("master_nodenum_toPrint:")
print(master_nodenum_toPrint)
print("condprobs_branch_bot:")
print(round(condprobs_branch_bot, 3))
print("downpass_relprobs_at_branch_top:")
print(round(downpass_relprobs_at_branch_top, 3))
print("condprobs_branch_top:")
print(round(condprobs_branch_top, 3))
print("probs_branch_top:")
print(round(probs_branch_top, 3))
}
TF1 = is.na(probs_branch_top)
TF2 = is.nan(probs_branch_top)
TF = (TF1 + TF2 ) > 0
if (sum(TF) > 0)
{
cat("\n\n")
print("ERROR in stochastic_map_given_inputs(): probs_branch_top had NA(s) or NaNs:")
print("probs_branch_top:")
printall(probs_branch_top)
cat("\n\n")
print("stochastic_map_given_inputs():")
print("rownum:")
print(rownum)
print("master_nodenum_toPrint:")
print(master_nodenum_toPrint)
print("condprobs_branch_bot:")
print(round(condprobs_branch_bot, 3))
print("downpass_relprobs_at_branch_top:")
print(round(downpass_relprobs_at_branch_top, 3))
print("condprobs_branch_top:")
print(round(condprobs_branch_top, 3))
print("probs_branch_top:")
print(round(probs_branch_top, 3))
}
# Sample the state
sampled_state_branch_top_1based = sample(x=1:numstates, size=1, replace=TRUE, prob=probs_branch_top)
sampled_state_branch_top_1based
if (is.na(sampled_state_branch_top_1based) == TRUE)
{
txt = paste0("STOP ERROR_line347 in stochastic_map_given_inputs(): sampled_state_branch_top_1based is NA.")
cat("\n\n")
cat(txt)
cat("\n\n")
print("probs_branch_top:")
printall(probs_branch_top)
stop(txt)
}
# Store the state
trtable$sampled_states_AT_nodes[subtable_rownum] = sampled_state_branch_top_1based
#######################################################
# Stochastic mapping, once the states at branch bottoms
# and branch tops have been sampled
# Specifically for root branches of sub-trees!!
# (left this out the first time -- 2014-05-28_NJM)
#######################################################
# Stochastic mapping of events on the subtree root branch
if (stochastic_mapping_inputs$store_stratum_states_list_TF == FALSE)
{
events_table_for_branch_below_subtree_root_node = stochastic_map_branch(nodenum_at_top_of_branch=subtable_rownum, trtable=trtable, Qmat=Qmat, state_indices_0based=state_indices_0based, ranges_list=ranges_list, areas=areas, stratified=stratified, maxtries=maxtries)
}
if (stochastic_mapping_inputs$store_stratum_states_list_TF == TRUE)
{
subset_nums = (1:length(stochastic_mapping_inputs$states_allowed_this_timeperiod_TF))[stochastic_mapping_inputs$states_allowed_this_timeperiod_TF]
# Expand the subset Qmat to be full-size
Qmat_big = matrix(data=0, nrow=length(stochastic_mapping_inputs$states_allowed_this_timeperiod_TF), ncol=length(stochastic_mapping_inputs$states_allowed_this_timeperiod_TF))
Qmat_big[subset_nums,subset_nums] = Qmat
events_table_for_branch_below_subtree_root_node = stochastic_map_branch(nodenum_at_top_of_branch=subtable_rownum, trtable=trtable, Qmat=Qmat_big, state_indices_0based=state_indices_0based, ranges_list=ranges_list, areas=areas, stratified=stratified, maxtries=maxtries)
}
# Store the text representation
# (extract to table with events_txt_into_events_table() )
subtree_root_branch_events_txt = events_table_into_txt(events_table_for_branch_below_subtree_root_node)
trtable$anagenetic_events_txt_below_node[subtable_rownum] = subtree_root_branch_events_txt
# End stochastic mapping on the branches below subtree root
} # END if ( (stratified == TRUE) && (rootedge == TRUE))
#######################################################
# UPPASS THROUGH THE NODE FROM THE ROOT NODE
# START FROM A NODE STATE, THEN SIMULATE THE TWO NODE STATES ABOVE,
# THEN SIMULATE THE BRANCH EVENTS
#######################################################
# Visit edges in reverse order from the downpass
edges_to_visit_uppass = seq(from=(num_internal_nodes*2), by=-2, length.out=num_internal_nodes)
# Since we are going backwards
#print(edges_to_visit_uppass)
#print(i)
#print(j)
#cat("\n")
#for (i in edges_to_visit_uppass)
#j=edges_to_visit_uppass[1]
cat("\nBeginning stochastic mapping UPPASS (i:Leftnode,j:Rightnode,anc:Ancnode;):\n", sep="")
for (j in edges_to_visit_uppass) # Since we are going backwards
{
# First edge visited is i
#print(i)
# Its sister is j
#j <- i - 1
i <- j - 1 # Since we are going backwards
# Get the node numbers at the tips of these two edges
left_desc_nodenum <- phy2$edge[i, 2]
right_desc_nodenum <- phy2$edge[j, 2]
# And for the ancestor edge (i or j shouldn't matter, should produce the same result!!!)
anc <- phy2$edge[i, 1]
# Store the node number (starting with the root)
nodenum = anc
cat(i, ":", left_desc_nodenum, ",", j, ":", right_desc_nodenum, ",anc:", anc, "; ", sep="")
# get the correct edges
left_edge_TF = phy2$edge[,2] == left_desc_nodenum
right_edge_TF = phy2$edge[,2] == right_desc_nodenum
# Check the branchlength of each edge
# It's a hook if either branch is super-short
is_leftbranch_hook_TF = phy2$edge.length[left_edge_TF] < min_branchlength
is_rightbranch_hook_TF = phy2$edge.length[right_edge_TF] < min_branchlength
hooknode_TF = (is_leftbranch_hook_TF + is_rightbranch_hook_TF) > 0
# Get the state at the current node (anc)
statenum_1based = trtable$sampled_states_AT_nodes[nodenum]
if (is.na(statenum_1based) == TRUE)
{
txt = paste0("STOP ERROR_line426 in stochastic_map_given_inputs(): statenum_1based is NA.")
cat("\n\n")
cat(txt)
cat("\n\n")
print("i:")
print(i)
print("j:")
print(j)
print("hooknode_TF:")
print(hooknode_TF)
print("nodenum:")
print(nodenum)
stop(txt)
}
#######################################################
# STOCHASTIC MAPPING OF CLADOGENETIC PROCESS
#######################################################
# FIRST, get the node nums
# 2017-04-07_bug fix: hooknodes weren't getting these
# The downpass probs of each state at each branch
if (stratified == FALSE)
{
# stratified == FALSE
# *************** perhaps use
# left_desc_nodenum and right_desc_nodenum
left_branch_decnode = trtable$left_desc_nodes[nodenum]
right_branch_decnode = trtable$right_desc_nodes[nodenum]
# *************** perhaps use
# left_desc_nodenum and right_desc_nodenum
# NOPE, THIS IS FINE -- 2014-12-29_NJM
if ( (left_desc_nodenum != left_branch_decnode) | (right_desc_nodenum != right_branch_decnode) )
{
print("left_desc_nodenum, right_desc_nodenum")
cat(left_desc_nodenum, right_desc_nodenum)
print("left_branch_decnode, right_branch_decnode")
cat(left_branch_decnode, right_branch_decnode)
stop()
}
left_branch_downpass_likes = res$relative_probs_of_each_state_at_branch_bottom_below_node_DOWNPASS[left_branch_decnode, ]
right_branch_downpass_likes = res$relative_probs_of_each_state_at_branch_bottom_below_node_DOWNPASS[right_branch_decnode, ]
} else {
# stratified==TRUE
daughter_nodenums_global = trtable$daughter_nds[nodenum][[1]]
# names(leftright_nodes_matrix) = c("right", "left")
# NJMtest switch left and right: NO. Should be 1,2
left_branch_decnode_global = daughter_nodenums_global[1]
right_branch_decnode_global = daughter_nodenums_global[2]
left_branch_downpass_likes = res$relative_probs_of_each_state_at_branch_bottom_below_node_DOWNPASS[left_branch_decnode_global, ]
right_branch_downpass_likes = res$relative_probs_of_each_state_at_branch_bottom_below_node_DOWNPASS[right_branch_decnode_global, ]
# Get the LOCAL left/right nodes, for the
# sub-table
left_branch_decnode_TF = trtable$node == left_branch_decnode_global
left_branch_decnode = (1:nrow(trtable))[left_branch_decnode_TF]
right_branch_decnode_TF = trtable$node == right_branch_decnode_global
right_branch_decnode = (1:nrow(trtable))[right_branch_decnode_TF]
left_branch_decnode
right_branch_decnode
} # END if (stratified == FALSE)
#print ("#1")
# If it's a hooknode, then copy the node state up
# (no sampling needed)
if (hooknode_TF == TRUE)
{
# Just copy the node state to the corners
#sampled_split_descendants = list()
#sampled_split_descendants$left_decstate_1based = statenum_1based
#sampled_split_descendants$right_decstate_1based = statenum_1based
# 2017-04-07_bug_fix
# *IF* a hook, copy the node state to both descendant corners
sample_uppass_res = list()
sample_uppass_res$left_decstate_1based = statenum_1based
sample_uppass_res$right_decstate_1based = statenum_1based
if (is.na(statenum_1based) == TRUE)
{
print("print(sample_uppass_res)")
print(sample_uppass_res)
stop("STOP ERROR_line477")
}
#print(statenum_1based)
#stop("STOP ERROR_line477a")
# These will get copied to the table outside of this loop
} else {
# If NOT a hooknode (typical), sample a pair of descendant states
# Calculate the probability of each range inheritance scenario,
# given the chosen root state
# -1 regardless of whether there is a null range (1 to 0 conversion)
index_Qmat_0based_of_starting_state = statenum_1based - 1
#RCOO_probs_list_given_ancestor = given_a_starting_state_get_prob_of_each_split_scenario(index_Qmat_0based_of_starting_state, COO_weights_columnar, numstates=numstates_during_cladogenesis, include_null_range=TRUE)
#uppass_probs_of_scenarios_given_root_state = RCOO_probs_list_given_ancestor
#uppass_probs_of_scenarios_given_root_state
#cbind(COO_weights_columnar[[1]], COO_weights_columnar[[2]], COO_weights_columnar[[3]], uppass_probs_of_scenarios_given_root_state)
#sampled_split_descendants = sample_split_scenario(COO_weights_columnar, uppass_probs_of_scenarios_given_root_state, left_branch_downpass_likes, right_branch_downpass_likes)
# Input the ancestral state into the state probabilities at the current node
statenum_1based
probs_ancstate = rep(0, length(left_branch_downpass_likes))
probs_ancstate[statenum_1based] = 1
probs_ancstate
# NJM -- for bug checking...
if (nodenum == 21)
{
printflag = TRUE
} else {
printflag = FALSE
}
# OLD (2014-05-ish)
#sampled_split_descendants = sample_split_scenario2(COO_weights_columnar, probs_ancstate, left_branch_downpass_likes, right_branch_downpass_likes, sample_which="both", return_prob_each_split_scenario=FALSE, include_null_range=TRUE, Rsp_rowsums=NULL, numstates_wo_null=NULL, printflag=printflag)
if (stochastic_mapping_inputs$store_stratum_states_list_TF == FALSE)
{
# NEW (2015-01-10)
sample_uppass_res = sample_uppass_split_scenario_given_probs_ancstate(probs_ancstate=probs_ancstate, COO_weights_columnar=COO_weights_columnar, numstates=numstates, include_null_range=include_null_range, left_branch_downpass_likes=left_branch_downpass_likes, right_branch_downpass_likes=right_branch_downpass_likes, Rsp_rowsums=NULL)
}
if (stochastic_mapping_inputs$store_stratum_states_list_TF == TRUE)
{
subset_nums = (1:length(stochastic_mapping_inputs$states_allowed_this_timeperiod_TF))[stochastic_mapping_inputs$states_allowed_this_timeperiod_TF]
probs_ancstate_subset = probs_ancstate[subset_nums]
numstates_subset = length(probs_ancstate_subset)
left_branch_downpass_likes_subset = left_branch_downpass_likes[subset_nums]
right_branch_downpass_likes_subset = right_branch_downpass_likes[subset_nums]
sample_uppass_res_subset = sample_uppass_split_scenario_given_probs_ancstate(probs_ancstate=probs_ancstate_subset, COO_weights_columnar=COO_weights_columnar, numstates=numstates_subset, include_null_range=include_null_range, left_branch_downpass_likes=left_branch_downpass_likes_subset, right_branch_downpass_likes=right_branch_downpass_likes_subset, Rsp_rowsums=NULL)
# Convert the sampled states in the subset list,
# to the sampled states in the full list
sample_uppass_res = list()
sample_uppass_res$left_decstate_1based = subset_nums[sample_uppass_res_subset$left_decstate_1based]
sample_uppass_res$right_decstate_1based = subset_nums[sample_uppass_res_subset$right_decstate_1based]
}
} # END if (hooknode_TF == TRUE)
# OLD
#left_decstate_1based = sampled_split_descendants$left_decstate_1based
#right_decstate_1based = sampled_split_descendants$right_decstate_1based
# NEW
left_decstate_1based = as.numeric(sample_uppass_res$left_decstate_1based)
right_decstate_1based = as.numeric(sample_uppass_res$right_decstate_1based)
#print(c("oldLeft", "oldRight", "newLeft", "newRight"))
#print(c(sampled_split_descendants$left_decstate_1based, sampled_split_descendants$right_decstate_1based, sample_uppass_res$left_decstate_1based, sample_uppass_res$right_decstate_1based))
# Put these into the trtable
trtable$samp_LEFT_dcorner[nodenum] = left_decstate_1based
trtable$samp_RIGHT_dcorner[nodenum] = right_decstate_1based
# And put them in as the sampled states at branch bottoms for the appropriate
# descendant nods
# left_branch_decnode and right_branch_decnode are LOCAL
# for the SUBTREE
trtable$sampled_states_AT_brbots[left_branch_decnode] = left_decstate_1based
trtable$sampled_states_AT_brbots[right_branch_decnode] = right_decstate_1based
if (isblank_TF(left_decstate_1based) == TRUE)
{
txt = paste0("STOP ERROR_line576 in stochastic_map_given_inputs(): left_decstate_1based is BLANK: left_decstate_1based='", left_decstate_1based, "'.")
stop(txt)
}
if (isblank_TF(right_decstate_1based) == TRUE)
{
txt = paste0("STOP ERROR_line576 in stochastic_map_given_inputs(): left_decstate_1based is BLANK: right_decstate_1based='", right_decstate_1based, "'.")
stop(txt)
}
#print ("#2")
#######################################################
# STOCHASTIC MAPPING OF ANAGENETIC PROCESS
#######################################################
# Now, evolution ALONG branches
#independent_likelihoods_on_each_branch = calc_independent_likelihoods_on_each_branch(phy2, Qmat, cluster_already_open=NULL, Qmat_is_sparse=FALSE)
# Steps:
# a. Given a state at a corner, calculate the conditional probabilities
# of states at the branch top.
# b. Multiply these by the saved downpass probabilities
# c. Sample from this distribution, & store at the nodes at the top
# Initialize the starting probabilities at branch bottoms
# (setting the P(known sampled state) to equal 1!!)
condprobs_Left_branch_top = rep(0, times=numstates)
condprobs_Right_branch_top = rep(0, times=numstates)
condprobs_Left_branch_bot = rep(0, times=numstates)
condprobs_Right_branch_bot = rep(0, times=numstates)
condprobs_Left_branch_bot[left_decstate_1based] = 1
condprobs_Right_branch_bot[right_decstate_1based] = 1
# Dense matrix exponentiation, which has been done already!
if (stochastic_mapping_inputs$store_stratum_states_list_TF == FALSE)
{
nothing = TRUE
} # END if (stochastic_mapping_inputs$store_stratum_states_list_TF == FALSE)
if (stochastic_mapping_inputs$store_stratum_states_list_TF == TRUE)
{
subset_nums = (1:length(stochastic_mapping_inputs$states_allowed_this_timeperiod_TF))[stochastic_mapping_inputs$states_allowed_this_timeperiod_TF]
# Change the size of the inputs
condprobs_Left_branch_bot_orig = condprobs_Left_branch_bot
condprobs_Right_branch_bot_orig = condprobs_Right_branch_bot
condprobs_Left_branch_top_orig = condprobs_Left_branch_top
condprobs_Right_branch_top_orig = condprobs_Right_branch_top
condprobs_Left_branch_bot = condprobs_Left_branch_bot[subset_nums]
condprobs_Right_branch_bot = condprobs_Right_branch_bot[subset_nums]
condprobs_Left_branch_top = condprobs_Left_branch_top[subset_nums]
condprobs_Right_branch_top = condprobs_Right_branch_top[subset_nums]
} # END if (stochastic_mapping_inputs$store_stratum_states_list_TF == TRUE)
TF2 = ( (length(cluster_already_open)==1) && (cluster_already_open==FALSE) )
if (is.null(cluster_already_open) || (TF2))
{
# Relative probabilities of states at the top of left branch
condprobs_Left_branch_top = try(condprobs_Left_branch_bot %*% independent_likelihoods_on_each_branch[,,i])
if (length(class(condprobs_Left_branch_top)) == 1)
{
if (class(condprobs_Left_branch_top) == "try-error")
{
print(i)
print(length(condprobs_Left_branch_bot))
print(dim(independent_likelihoods_on_each_branch[,,i]))
#print(condprobs_Left_branch_top)
save(condprobs_Left_branch_bot, file="condprobs_Left_branch_bot.Rdata")
save(independent_likelihoods_on_each_branch, file="independent_likelihoods_on_each_branch.Rdata")
save(independent_likelihoods_on_each_branch[,,i], file="independent_likelihoods_on_each_branch_i.Rdata")
print("STOPPING on error in 'condprobs_Left_branch_bot %*% independent_likelihoods_on_each_branch[,,i]'")
stop("STOPPING on error in 'condprobs_Left_branch_bot %*% independent_likelihoods_on_each_branch[,,i]'")
}
}
# Relative probabilities of states at the top of right branch
condprobs_Right_branch_top = try(condprobs_Right_branch_bot %*% independent_likelihoods_on_each_branch[,,j])
if (length(class(condprobs_Right_branch_top)) == 1)
{
if (class(condprobs_Right_branch_top) == "try-error")
{
print(j)
print(length(condprobs_Right_branch_bot))
print(dim(independent_likelihoods_on_each_branch[,,j]))
#print(condprobs_Right_branch_top)
save(condprobs_Right_branch_bot, file="condprobs_Right_branch_bot.Rdata")
save(independent_likelihoods_on_each_branch, file="independent_likelihoods_on_each_branch.Rdata")
save(independent_likelihoods_on_each_branch[,,j], file="independent_likelihoods_on_each_branch_i.Rdata")
print("STOPPING on error in 'condprobs_Right_branch_bot %*% independent_likelihoods_on_each_branch[,,j]'")
stop("STOPPING on error in 'condprobs_Right_branch_bot %*% independent_likelihoods_on_each_branch[,,j]'")
}
}
} else {
# Here, the independent_likelihoods_on_each_branch are stored in a list of matrices
# Relative probabilities of states at the top of left branch
condprobs_Left_branch_top = condprobs_Left_branch_bot %*% independent_likelihoods_on_each_branch[[i]]
# Relative probabilities of states at the top of right branch
condprobs_Right_branch_top = condprobs_Right_branch_bot %*% independent_likelihoods_on_each_branch[[j]]
} # END if (is.null(cluster_already_open))
#print ("#3")
# Un-subset the results
if (stochastic_mapping_inputs$store_stratum_states_list_TF == TRUE)
{
subset_nums = (1:length(stochastic_mapping_inputs$states_allowed_this_timeperiod_TF))[stochastic_mapping_inputs$states_allowed_this_timeperiod_TF]
# Change the size of the outputs
condprobs_Left_branch_bot_subset = condprobs_Left_branch_bot
condprobs_Right_branch_bot_subset = condprobs_Right_branch_bot
condprobs_Left_branch_top_subset = condprobs_Left_branch_top
condprobs_Right_branch_top_subset = condprobs_Right_branch_top
condprobs_Left_branch_bot = rep(0, times=length(stochastic_mapping_inputs$states_allowed_this_timeperiod_TF))
condprobs_Right_branch_bot = rep(0, times=length(stochastic_mapping_inputs$states_allowed_this_timeperiod_TF))
condprobs_Left_branch_top = rep(0, times=length(stochastic_mapping_inputs$states_allowed_this_timeperiod_TF))
condprobs_Right_branch_top = rep(0, times=length(stochastic_mapping_inputs$states_allowed_this_timeperiod_TF))
condprobs_Left_branch_bot[subset_nums] = condprobs_Left_branch_bot_subset
condprobs_Right_branch_bot[subset_nums] = condprobs_Right_branch_bot_subset
condprobs_Left_branch_top[subset_nums] = condprobs_Left_branch_top_subset
condprobs_Right_branch_top[subset_nums] = condprobs_Right_branch_top_subset
} # END if (stochastic_mapping_inputs$store_stratum_states_list_TF == TRUE)
# zero out the NULL range, since it is impossible in a survivor
# 2021-06-22_NJM allow null tips means, possibly, sister groups with null ranges
# (at least, Michael Nicolai has this)
dont_zero_out_nulls = TRUE
if ((include_null_range == TRUE) && (allow_null_tips == FALSE) && (dont_zero_out_nulls==TRUE))
{
condprobs_Left_branch_top[1] = 0
condprobs_Right_branch_top[1] = 0
} # END if (include_null_range == TRUE)
# Get the probabilities at the branch tops for the two branches above the node
# under consideration
# In non-stratified -- these are just the node numbers
# In stratified analysis:
# Here, left_desc_nodenum & right_desc_nodenum are for the SUBTREE
if (stratified == FALSE)
{
# NJM CHECK!!
# OK, now multiply the UPPASS and DOWNPASS probabilities
# 2015 version - prob OK
probs_Left_branch_top = condprobs_Left_branch_top * res$relative_probs_of_each_state_at_branch_top_AT_node_DOWNPASS[left_desc_nodenum,]
probs_Right_branch_top = condprobs_Right_branch_top * res$relative_probs_of_each_state_at_branch_top_AT_node_DOWNPASS[right_desc_nodenum,]
if ( (condprobs_Left_branch_top[1] == 1) && (include_null_range == TRUE))
{
txt = "NOTE CAREFULLY in stochastic_map_given_inputs(): the 1st cell of 'condprobs_Left_branch_top' equals 1.0. This means all of the probability is on the null range. This probably means you have high 'e', and multiple tips in the null range, perhaps as sister groups. This is a quite odd situation that can easily lead to 0/0 errors, because formally speaking, null ranges are impossible ancestral ranges at nodes. NJM has programmed a workaround to allow it if allow_null_tips==TRUE, such that the null range probabilities are not zeroed out at nodes, but: THINK VERY CAREFULLY IF YOU MEANT TO DO THIS AND REALLY THINK IT IS A GOOD IDEA."
cat("\n\n")
cat(txt)
cat("\n\n")
warning(txt)
}
if ( (condprobs_Right_branch_top[1] == 1) && (include_null_range == TRUE))
{
txt = "NOTE CAREFULLY in stochastic_map_given_inputs(): the 1st cell of 'condprobs_Right_branch_top' equals 1.0. This means all of the probability is on the null range. This probably means you have high 'e', and multiple tips in the null range, perhaps as sister groups. This is a quite odd situation that can easily lead to 0/0 errors, because formally speaking, null ranges are impossible ancestral ranges at nodes. NJM has programmed a workaround to allow it if allow_null_tips==TRUE, such that the null range probabilities are not zeroed out at nodes, but: THINK VERY CAREFULLY IF YOU MEANT TO DO THIS AND REALLY THINK IT IS A GOOD IDEA."
cat("\n\n")
cat(txt)
cat("\n\n")
warning(txt)
}
TF = isblank_TF(probs_Left_branch_top)
if ( (sum(TF) > 0) || (sum(probs_Left_branch_top) == 0))
{
txt = "STOP ERROR in stochastic_map_given_inputs(): NA/NaN in probs_Left_branch_top, OR sum(probs_Left_branch_top) == 0). Printing 'probs_Left_branch_top':"
cat("\n\n")
cat(txt)
cat("\n\n")
print("condprobs_Left_branch_top")
printall(condprobs_Left_branch_top)
cat("\n\n")
print("res$relative_probs_of_each_state_at_branch_top_AT_node_DOWNPASS[left_desc_nodenum,]")
tmprow = res$relative_probs_of_each_state_at_branch_top_AT_node_DOWNPASS[left_desc_nodenum,]
print(tmprow)
cat("\n\n")
print("probs_Left_branch_top")
printall(probs_Left_branch_top)
cat("\n\n")
stop(txt)
}
TF = isblank_TF(probs_Right_branch_top)
if ( (sum(TF) > 0) || (sum(probs_Right_branch_top) == 0))
{
txt = "STOP ERROR in stochastic_map_given_inputs(): NA/NaN in probs_Right_branch_top, OR sum(probs_Right_branch_top) == 0). Printing 'probs_Right_branch_top':"
cat("\n\n")
cat(txt)
cat("\n\n")
print("condprobs_Right_branch_top")
printall(condprobs_Right_branch_top)
cat("\n\n")
print("res$relative_probs_of_each_state_at_branch_top_AT_node_DOWNPASS[right_desc_nodenum,]")
tmprow = res$relative_probs_of_each_state_at_branch_top_AT_node_DOWNPASS[right_desc_nodenum,]
print(tmprow)
cat("\n\n")
print("probs_Left_branch_top")
printall(probs_Right_branch_top)
cat("\n\n")
stop(txt)
}
# In case users want to trace what's going on
left_desc_nodenum_global = left_desc_nodenum
right_desc_nodenum_global = right_desc_nodenum
# NJMfix: 2018-12-20
} else {
# When stratified == TRUE, we have to dig up the corresponding rows of res
# to get the correct downpass condlikes
# Left node
TF1 = res$inputs$master_table$node == trtable$node[left_desc_nodenum]
TF2 = res$inputs$master_table$stratum == trtable$stratum[left_desc_nodenum]
TF3 = res$inputs$master_table$piecenum == trtable$piecenum[left_desc_nodenum]
TF4 = res$inputs$master_table$piececlass == "subtree"
left_desc_nodenum_global_TF = (TF1 + TF2 + TF3 + TF4) == 4
left_desc_nodenum_global = (1:nrow(res$condlikes))[left_desc_nodenum_global_TF]
# Right node
TF1 = res$inputs$master_table$node == trtable$node[right_desc_nodenum]
TF2 = res$inputs$master_table$stratum == trtable$stratum[right_desc_nodenum]
TF3 = res$inputs$master_table$piecenum == trtable$piecenum[right_desc_nodenum]
TF4 = res$inputs$master_table$piececlass == "subtree"
right_desc_nodenum_global_TF = (TF1 + TF2 + TF3 + TF4) == 4
right_desc_nodenum_global = (1:nrow(res$condlikes))[right_desc_nodenum_global_TF]
# OK, now multiply the UPPASS and DOWNPASS probabilities
# print("condprobs_Left_branch_top")
# print(condprobs_Left_branch_top)
#
# print("res$condlikes[left_desc_nodenum_global,]")
# print(res$condlikes[left_desc_nodenum_global,])
#
#
# print("condprobs_Right_branch_top")
# print(condprobs_Right_branch_top)
#
# print("res$condlikes[right_desc_nodenum_global,]")
# print(res$condlikes[right_desc_nodenum_global,])
probs_Left_branch_top = condprobs_Left_branch_top * res$condlikes[left_desc_nodenum_global,]
probs_Right_branch_top = condprobs_Right_branch_top * res$condlikes[right_desc_nodenum_global,]
} # END if (stratified == FALSE)
printflag2 = FALSE
if (printflag2)
{
cat("\n\n")
print ("#4.5")
cat("\n\n")
print("probs_Left_branch_top")
printall(probs_Left_branch_top)
cat("\n\n")
print("sum(probs_Left_branch_top)")
print(sum(probs_Left_branch_top))
cat("\n\n")
cat("\n\n")
print ("#4.5b")
cat("\n\n")
print("probs_Right_branch_top")
printall(probs_Right_branch_top)
cat("\n\n")
print("sum(probs_Right_branch_top)")
print(sum(probs_Right_branch_top))
cat("\n\n")
}
# Normalize by sum so they add to 1
probs_Left_branch_top = probs_Left_branch_top / sum(probs_Left_branch_top)
probs_Right_branch_top = probs_Right_branch_top / sum(probs_Right_branch_top)
# print("left_desc_nodenum_global:")
# print(left_desc_nodenum_global)
# print("right_desc_nodenum_global:")
# print(right_desc_nodenum_global)
#print("Checking:")
# print ("#5")
# printall(probs_Left_branch_top)
# printall(probs_Right_branch_top)
TF = isblank_TF(probs_Left_branch_top)
if (sum(TF) > 0)
{
txt = "STOP ERROR in stochastic_map_given_inputs(): NA/NaN in probs_Left_branch_top. Printing 'probs_Left_branch_top':"
cat("\n\n")
print("probs_Left_branch_top")
printall(probs_Left_branch_top)
cat("\n\n")
stop(txt)
}
TF = isblank_TF(probs_Right_branch_top)
if (sum(TF) > 0)
{
txt = "STOP ERROR in stochastic_map_given_inputs(): NA/NaN in probs_Right_branch_top. Printing 'probs_Right_branch_top':"
cat("\n\n")
print("probs_Left_branch_top")
printall(probs_Right_branch_top)
cat("\n\n")
stop(txt)
}
#for (zzz in 1:20)
# {
# Sample states at the top of the two descendant branches
# (these are conditional on the uppass probs, conditional on the
# present node, AND on the saved downpass probs
sampled_state_Left_branch_top_1based = sample(x=1:numstates, size=1, replace=TRUE, prob=probs_Left_branch_top)
#print(sampled_state_Left_branch_top_1based)
if (isblank_TF(sampled_state_Left_branch_top_1based) == TRUE)
{
txt = paste0("STOP ERROR_line715 in stochastic_map_given_inputs(): sampled_state_Left_branch_top_1based is NA or NaN.")
cat("\n\n")
cat(txt)
cat("\n\n")
print("probs_Left_branch_top:")
printall(probs_Left_branch_top)
stop(txt)
}
#print ("#6")
sampled_state_Right_branch_top_1based = sample(x=1:numstates, size=1, replace=TRUE, prob=probs_Right_branch_top)
#print(sampled_state_Right_branch_top_1based)
if (isblank_TF(sampled_state_Right_branch_top_1based) == TRUE)
{
txt = paste0("STOP ERROR_line728 in stochastic_map_given_inputs(): sampled_state_Right_branch_top_1based is NA.")
cat("\n\n")
cat(txt)
cat("\n\n")
print("probs_Right_branch_top:")
printall(probs_Right_branch_top)
stop(txt)
}
# Store these states
trtable$sampled_states_AT_nodes[left_branch_decnode] = sampled_state_Left_branch_top_1based
trtable$sampled_states_AT_nodes[right_branch_decnode] = sampled_state_Right_branch_top_1based
#print ("#7")
if (stratified == FALSE)
{
master_nodenum = left_desc_nodenum
} else {
master_nodenum = res$inputs$master_table$node[left_desc_nodenum_global]
} # END if (stratified == FALSE)
if (master_nodenum == master_nodenum_toPrint)
{
cat("\n")
print("left_branch_decnode:")
print(left_branch_decnode)
print("condprobs_Left_branch_bot:")
print(round(condprobs_Left_branch_bot,3))
print("condprobs_Left_branch_top:")
print(round(condprobs_Left_branch_top,3))
print("res$condlikes[left_desc_nodenum_global,]:")
print(round(res$condlikes[left_desc_nodenum_global,],3))
print("probs_Left_branch_top:")
print(round(probs_Left_branch_top,3))
print("sampled_state_Left_branch_top_1based:")
print(round(sampled_state_Left_branch_top_1based,3))
sampled_stateprobs = rep(0, numstates)
sampled_stateprobs[sampled_state_Left_branch_top_1based] = 1
print("sampled_stateprobs:")
print(sampled_stateprobs)
cat("\n")
}
if (stratified == FALSE)
{
master_nodenum = right_desc_nodenum
} else {
master_nodenum = res$inputs$master_table$node[right_desc_nodenum_global]
} # END if (stratified == FALSE)
if (master_nodenum == master_nodenum_toPrint)
{
cat("\n")
print("right_branch_decnode:")
print(right_branch_decnode)
print("condprobs_Right_branch_bot:")
print(round(condprobs_Right_branch_bot,3))
print("condprobs_Right_branch_top:")
print(round(condprobs_Right_branch_top,3))
print("res$condlikes[right_desc_nodenum_global,]:")
print(round(res$condlikes[right_desc_nodenum_global,],3))
print("probs_Right_branch_top:")
print(round(probs_Right_branch_top,3))
print("sampled_state_Right_branch_top_1based:")
print(round(sampled_state_Right_branch_top_1based,3))
sampled_stateprobs = rep(0, numstates)
sampled_stateprobs[sampled_state_Right_branch_top_1based] = 1
print("sampled_stateprobs:")
print(sampled_stateprobs)
cat("\n")
}
#txt = paste0("zzz: ", zzz, ", L: ", left_decstate_1based, "->", sampled_state_Left_branch_top_1based, "; R: ", right_decstate_1based, "->", sampled_state_Right_branch_top_1based)
#cat("\n")
#cat(txt)
#} # END zzz
#cat("\n")
# CHECK LEFT-RIGHT NODE NUMBERING
check_left_vs_right_numbering = FALSE
# NOTE: FOR TREE ITERATIONS, YOU HAVE TO SWITCH
# LEFT AND RIGHT, WHICH IS DIFFERENT THAN
# FOR GRAPHING:
# # Add the right and left descendant node numbers
# leftright_nodes_matrix = get_leftright_nodes_matrix_from_results(phy2)
#
# left_desc_nodes = rep(NA, nrow(trtable))
# right_desc_nodes = rep(NA, nrow(trtable))
#
# # dcorner = descendant corner (i.e. right after speciation)
# samp_LEFT_dcorner = rep(NA, nrow(trtable))
# samp_RIGHT_dcorner = rep(NA, nrow(trtable))
#
# trtable = cbind(trtable, left_desc_nodes, right_desc_nodes, samp_LEFT_dcorner, samp_RIGHT_dcorner)
# trtable$left_desc_nodes[nodenums] = leftright_nodes_matrix$right
# trtable$right_desc_nodes[nodenums] = leftright_nodes_matrix$left
# trtable[nodenums,]
if (check_left_vs_right_numbering == TRUE)
{
if (left_branch_decnode <= ntips)
{
print("Left tip:")
print(left_branch_decnode)
print(left_desc_nodenum)
print(sampled_state_Left_branch_top_1based)
printall(probs_Left_branch_top)
} # END if (left_branch_decnode <= ntips)
if (right_branch_decnode <= ntips)
{
print("Right tip:")
print(right_branch_decnode)
print(right_desc_nodenum)
print(sampled_state_Right_branch_top_1based)
printall(probs_Right_branch_top)
} # END if (right_branch_decnode <= ntips)
} # END if (check_left_vs_right_numbering == TRUE)
#######################################################
# Stochastic mapping, once the states at branch bottoms
# and branch tops have been sampled
#######################################################
if (stochastic_mapping_inputs$store_stratum_states_list_TF == FALSE)
{
# Stochastic mapping of events on the left branch
events_table_for_branch_below_Left_node = stochastic_map_branch(nodenum_at_top_of_branch=left_branch_decnode, trtable=trtable, Qmat=Qmat, state_indices_0based=state_indices_0based, ranges_list=ranges_list, areas=areas, stratified=stratified, maxtries=maxtries)
# Stochastic mapping of events on the right branch
events_table_for_branch_below_Right_node = stochastic_map_branch(nodenum_at_top_of_branch=right_branch_decnode, trtable=trtable, Qmat=Qmat, state_indices_0based=state_indices_0based, ranges_list=ranges_list, areas=areas, stratified=stratified, maxtries=maxtries)
}
if (stochastic_mapping_inputs$store_stratum_states_list_TF == TRUE)
{
# Expand the subset Qmat to be full-size
subset_nums = (1:length(stochastic_mapping_inputs$states_allowed_this_timeperiod_TF))[stochastic_mapping_inputs$states_allowed_this_timeperiod_TF]
Qmat_big = matrix(data=0, nrow=length(stochastic_mapping_inputs$states_allowed_this_timeperiod_TF), ncol=length(stochastic_mapping_inputs$states_allowed_this_timeperiod_TF))
Qmat_big[subset_nums,subset_nums] = Qmat
# Stochastic mapping of events on the left branch
events_table_for_branch_below_Left_node = stochastic_map_branch(nodenum_at_top_of_branch=left_branch_decnode, trtable=trtable, Qmat=Qmat_big, state_indices_0based=state_indices_0based, ranges_list=ranges_list, areas=areas, stratified=stratified, maxtries=maxtries)
# Stochastic mapping of events on the right branch
events_table_for_branch_below_Right_node = stochastic_map_branch(nodenum_at_top_of_branch=right_branch_decnode, trtable=trtable, Qmat=Qmat_big, state_indices_0based=state_indices_0based, ranges_list=ranges_list, areas=areas, stratified=stratified, maxtries=maxtries)
}
# Store the text representation
# (extract to table with events_txt_into_events_table() )
left_branch_events_txt = events_table_into_txt(events_table_for_branch_below_Left_node)
right_branch_events_txt = events_table_into_txt(events_table_for_branch_below_Right_node)
trtable$anagenetic_events_txt_below_node[left_branch_decnode] = left_branch_events_txt
trtable$anagenetic_events_txt_below_node[right_branch_decnode] = right_branch_events_txt
# print(left_branch_decnode)
# print(left_branch_events_txt)
# print(right_branch_decnode)
# print(right_branch_events_txt)
} # END for (j in edges_to_visit_uppass)
# (ENDING uppass loop)
# Some of these are getting skipped??
#stochastic_mapping_inputs_list[[11]]$master_table_timeperiod_i$sampled_states_AT_nodes
#master_table_timeperiod_i$sampled_states_AT_nodes
if (any(is.na(trtable$sampled_states_AT_nodes)))
{
txt = paste0("STOP ERROR_line923 in stochastic_map_given_inputs(): These trtable$sampled_states_AT_nodes are still NA!")
cat("\n\n")
cat(txt)
cat("\n\n")
print("Rows that are still NA:")
rows_still_NA = (1:length(trtable$sampled_states_AT_nodes))[is.na(trtable$sampled_states_AT_nodes)]
print( rows_still_NA )
print("print(trtable[is.na(trtable$sampled_states_AT_nodes),])")
print(trtable[is.na(trtable$sampled_states_AT_nodes),])
print(trtable[trtable$SUBedge.length<min_branchlength,])
stop(txt)
}
cat("\n...finished stochastic mapping UPPASS.\n", sep="")
# trtable$anagenetic_events_txt_below_node
# trtable = add_cladogenetic_events_to_trtable(trtable=trtable_good, BioGeoBEARS_run_object=res$inputs, tipranges, stratified=stratified, piecenum=NULL)
# trtable$anagenetic_events_txt_below_node
#print(trtable$anagenetic_events_txt_below_node)
cat("Adding cladogenetic events and re-arranging columns...\n", sep="")
# Add cladogenetic events and re-arrange columns
if (stratified == FALSE)
{
trtable = add_cladogenetic_events_to_trtable(trtable, BioGeoBEARS_run_object=res$inputs, tipranges, stratified=stratified, piecenum=NULL)
} else {
trtable = add_cladogenetic_events_to_trtable(trtable, BioGeoBEARS_run_object=res$inputs, tipranges, stratified=stratified, piecenum=piecenum)
}
cat("DONE adding cladogenetic events and re-arranging columns.\n", sep="")
#print(trtable$anagenetic_events_txt_below_node)
cat("FINISHING stochastic_map_given_inputs().\n", sep="")
# If stratified, don't rearrange
# If not stratified, *do* rearrange
if (stratified == FALSE)
{
first_colnums = 1:(ncol(trtable)-4)
last4_colnums = (ncol(trtable)-3):(ncol(trtable))
new_colnums = c(first_colnums, last4_colnums[c(2,3,4,1)])
trtable = trtable[,new_colnums]
}
# Convert master_table_timeperiod_i to trtable
if (stratified == TRUE)
{
#cat("\n\nprint(dim(trtable)):\n\n")
#print(dim(trtable))
#cat("\n\nprint(master_table_timeperiod_i[subtable_rownums,]):\n\n")
#print(master_table_timeperiod_i[subtable_rownums,])
# We may be modifying just PART of the subtable
stochastic_mapping_inputs$master_table_timeperiod_i[subtable_rownums,] = trtable
# Look at results
stochastic_mapping_inputs$master_table_timeperiod_i
return(stochastic_mapping_inputs$master_table_timeperiod_i)
} else {
# Look at results
trtable[nodenums,]
return(trtable)
}
return(stop("ERROR: you should not reach this."))
} # END stochastic_map_given_inputs <- function(stochastic_mapping_inputs, piecenum=NULL, maxtries=40000, seedval=12345, include_null_range)
#
# For stochastic mapping on non-stratified analysis:
#
# stochastic_mapping_inputs = get_inputs_for_stochastic_mapping_from_results_object(res=resDEC)
# stochastic_mapping_results = stochastic_map_given_inputs(stochastic_mapping_inputs)
#
# For stochastic mapping on stratified analysis:
#
# stochastic_mapping_inputs_list = get_inputs_for_stochastic_mapping_stratified(res=resDEC)
# stochastic_mapping_results = stochastic_mapping_on_stratified(res=resDEC, stochastic_mapping_inputs_list=stochastic_mapping_inputs_list)
#
#######################################################
# stochastic_mapping_on_stratified()
#######################################################
#
# Do stochastic mapping on the results of a stratified analysis, given
# (1) a results object from bears_optim_run
# (2) a list of stochastic mapping inputs generated
# as follows:
# # Get stochastic mapping inputs for stratified analysis
# stochastic_mapping_inputs_list = list()
# for (timeperiod_i in 1:length(res$inputs$tree_sections_list))
# {
# stochastic_mapping_inputs = get_inputs_for_stochastic_mapping_from_results_object(res=res, stratified=stratified, timeperiod_i=timeperiod_i)
#
# stochastic_mapping_inputs_list[[timeperiod_i]] = stochastic_mapping_inputs
# } # END for (timeperiod_i in 1:length(res$inputs$tree_sections_list))
#
#######################################################
stochastic_mapping_on_stratified <- function(res, stochastic_mapping_inputs_list, maxtries=40000, seedval=as.numeric(Sys.time()), master_nodenum_toPrint=0)
{
# Necessary setting to avoid getting numbers etc. in the stochastic mapping output
options(stringsAsFactors=FALSE)
# Set the seed
#print(paste0("stochastic_mapping_on_stratified seedval=", seedval, sep=""))
if (seedval > 2147483647)
{
seedval = seedval %% 2147483647
}
set.seed(seedval)
# Seed increment counter for tree pieces
treepiece_seed_counter_increment = 90127 # (large prime number)
treepiece_seed_counter = 1
# Set stratified=TRUE, obviously -- put in error catch for non-stratified analysis.
if (is.na(res$inputs$timesfn) == TRUE)
{
stratified=FALSE
errortxt = "STOP ERROR in stochastic_mapping_on_stratified().\n\nThe 'res' object that you input to this function has no input times filename.\n\nSpecifically, res$inputs$timesfn equals NA. This suggests that the 'res' input\n\nwas generated by a non-stratified analysis. In that case, you should use\n\nstochastic_map_given_inputs() instead of stochastic_mapping_on_stratified() for \n\nBiogeographical Stochastic Mapping (BSM) in BioGeoBEARS\n\n."
cat(errortxt)
stop(errortxt)
} else {
stratified=TRUE
}
# Get results from the likelihood analysis
# (for input to:
# get_tip_likelihoods_of_subbranch_from_resCondlikes_given_master_table )
master_table = res$inputs$master_table
condlikes = res$condlikes_table
relative_probs_of_each_state_at_branch_bottom_below_node_DOWNPASS_TABLE = res$relative_probs_of_each_state_at_branch_bottom_below_node_DOWNPASS_TABLE
# Error check
if (is.null(relative_probs_of_each_state_at_branch_bottom_below_node_DOWNPASS_TABLE))
{
errortxt = "STOP ERROR in stochastic_mapping_on_stratified():\n\nres$relative_probs_of_each_state_at_branch_bottom_below_node_DOWNPASS_TABLE is NULL.\n\nThis will occur on results_objects (res) that were made by bears_optim_run()\n before about May 2014. Please re-run the ML inference with updated package/sourcefiles before\nrunning Biogeographic Stochastic Mapping.\n\nOr, perhaps you are accidentally using stochastic_mapping_on_stratified() when your input ML analysis was non-stratified. In that case, you should use stochastic_map_given_inputs() instead.\n\nHave a nice day.\n\n"
cat(errortxt)
stop(errortxt)
} # END if (is.null(relative_probs_of_each_state_at_branch_bottom_below_node_DOWNPASS_TABLE))
# Get the root state
num_timeperiods = length(res$inputs$timeperiods)
stochastic_mapping_inputs = stochastic_mapping_inputs_list[[num_timeperiods]]
subtable = stochastic_mapping_inputs$master_table_timeperiod_i
rootTF = subtable$node.type == "root"
if (sum(rootTF) != 1)
{
errortxt = paste("\n\nERROR: Your bottom tree section, timeperiod_i=", num_timeperiods, ", does not contain a node of node.type 'root'\nin $master_table_timeperiod_i:\n\n", sep="")
cat(errortxt)
} else {
rootnode = subtable$node[rootTF]
}
rootnode
numstates = ncol(res$ML_marginal_prob_each_state_at_branch_top_AT_node)
node_stateprobs = res$ML_marginal_prob_each_state_at_branch_top_AT_node[rootnode,]
statenums = 1:numstates
statenum_1based = sample(x=statenums, size=1, replace=TRUE, prob=node_stateprobs)
statenum_1based
if (is.na(statenum_1based) == TRUE)
{
txt = paste0("STOP ERROR_line1013 in stochastic_map_given_inputs(): statenum_1based is NA.")
cat("\n\n")
cat(txt)
cat("\n\n")
print("node_stateprobs:")
print(node_stateprobs)
stop(txt)
}
# Store the root state in the master table
stochastic_mapping_inputs_list[[num_timeperiods]]$master_table_timeperiod_i$sampled_states_AT_nodes[rootTF] = statenum_1based
# The treepiece in the BOTTOM stratum should ALWAYS be a subtree and
# NEVER a root branch
# Now, you have to walk up the time pieces (including root branches)
timeperiod_i = num_timeperiods
for (timeperiod_i in num_timeperiods:1)
{
stratum = timeperiod_i
timeperiod_i_up = timeperiod_i - 1
stochastic_mapping_inputs = stochastic_mapping_inputs_list[[timeperiod_i]]
master_table_timeperiod_i = stochastic_mapping_inputs$master_table_timeperiod_i
# if (any(is.na(master_table_timeperiod_i$sampled_states_AT_nodes)))
# {
# txt = paste0("STOP ERROR_line1085 in (): Some of master_table_timeperiod_i$sampled_states_AT_nodes are NA. Specifically, these:")
# cat("\n\n")
# cat(txt)
# print("print( (1:length(master_table_timeperiod_i$sampled_states_AT_nodes))[is.na(master_table_timeperiod_i$sampled_states_AT_nodes)] )")
#
# print( (1:length(master_table_timeperiod_i$sampled_states_AT_nodes))[is.na(master_table_timeperiod_i$sampled_states_AT_nodes)] )
# print("timeperiod_i")
# print(timeperiod_i)
#
# print("piecenum")
# print(piecenum)
#
# cat("\n\n")
# stop(txt)
# }
tree_sections = stochastic_mapping_inputs$tree_sections_list
tree_pieces = tree_sections$return_pieces_list
num_pieces = length(tree_pieces)
# Get the independent likelihoods
independent_likelihoods_by_tree_piece_for_timeperiod_i = stochastic_mapping_inputs$independent_likelihoods_by_tree_piece_for_timeperiod_i
# Get the transition rate parameters
Qmat = stochastic_mapping_inputs$Qmat
COO_weights_columnar = stochastic_mapping_inputs$COO_weights_columnar
Rsp_rowsums = stochastic_mapping_inputs$Rsp_rowsums
state_indices_0based = stochastic_mapping_inputs$state_indices_0based
ranges_list = stochastic_mapping_inputs$ranges_list
areas = stochastic_mapping_inputs$areas
piecenum = 1
for (piecenum in 1:num_pieces)
{
# 2016-05-07_bugfix
# seedval = 24785446
# timeperiod_i =1
# piecenum = 10
#print("Apiecenum:")
tree_piece = tree_pieces[[piecenum]]
error_check_Psychotria_all_tips_size1 = FALSE
if (error_check_Psychotria_all_tips_size1)
{
cat("\n\n\n\n")
print("timeperiod_i")
print(timeperiod_i)
print("stratum")
print(stratum)
print("piecenum")
print(piecenum)
} # END if (error_check_Psychotria_all_tips_size1)
if (is.numeric(tree_piece))
{
#print("Apiecenum:")
#print(tree_piece)
# Piece is a single branch; stochastically map on just that branch
single_branch = TRUE
#######################################################
# NOTE: For SINGLE BRANCHES, let's use:
# sampled_states_AT_brbots = state at the bottom of the branch
# (previously sampled)
# sampled_states_AT_nodes = state at the top of the branch
# (sampled at the end of this step)
#######################################################
# Simulate up from the (pre-determined) bottom of the branch
#master_table_timeperiod_i$sampled_states_AT_brbots[subtable_rownum] = 2
# Get the pre-determined starting state
rowTF = master_table_timeperiod_i$piecenum == piecenum
subtable_rownum = (1:nrow(master_table_timeperiod_i))[rowTF]
starting_state_1based = master_table_timeperiod_i$sampled_states_AT_brbots[subtable_rownum]
starting_state_1based
#print("print(timeperiod_i):")
#print(timeperiod_i)
#print("print(subtable_rownum):")
#print(subtable_rownum)
#print("print(master_table_timeperiod_i[subtable_rownum, ]):")
#print(master_table_timeperiod_i[subtable_rownum, ])
if (isblank_TF(starting_state_1based) == TRUE)
{
stop("STOP_in_stochastic_map_given_inputs.R_line_1756")
}
# Find the downpass conditional likelihoods (normalized) that have
# been pre-calculated
#
# Inputs:
# res$condlikes -- contains downpass branch-top likelihoods for
# nodes at the tops of branches in subtrees, and for the
# bottoms of subbranches
# res$condlikes -- contains downpass branch-top likelihoods for
# nodes at the tops of branches in subtrees, and for the
# bottoms of subbranches
# Contains all of the tree pieces and their references to the master tree
# res$inputs$master_table
# START CHECK IF THERE IS ONLY ONE ROW (redundant)
TF1 = res$inputs$master_table$node == master_table_timeperiod_i$node[subtable_rownum]
TF2 = res$inputs$master_table$stratum == master_table_timeperiod_i$stratum[subtable_rownum]
TF3 = res$inputs$master_table$piecenum == master_table_timeperiod_i$piecenum[subtable_rownum]
TF4 = res$inputs$master_table$piececlass != "subtree"
TF = (TF1 + TF2 + TF3 + TF4) == 4
rownums = 1:nrow(res$inputs$master_table)
rownum_master_table = rownums[TF]
rownum = rownum_master_table
#master_nodenum = res$inputs$master_table$node[rownum_master_table]
#print(master_nodenum)
if (length(rownum) != 1)
{
errortxt = paste("\n\nERROR in identifying corresponding subbranch in res$inputs$master_table.\nlength(rownum) should be 1, but is actually: ", length(rownum), "\n\n", sep="")
cat(errortxt)
cat("\n\n")
cat("timeperiod_i=", timeperiod_i, sep="")
cat("\n")
cat("piecenum=", piecenum, sep="")
cat("\n\n")
cat("master_table_timeperiod_i:")
cat("\n\n")
printall(master_table_timeperiod_i)
stop("\n\nStopping on error.")
} # END check if there is only 1 row
# Inputs
condlikes = res$condlikes
relative_probs_of_each_state_at_branch_bottom_below_node_DOWNPASS_TABLE = res$relative_probs_of_each_state_at_branch_bottom_below_node_DOWNPASS_TABLE
# Get the tip likelihoods, including subbranches in the
# top stratum (#1) corresponding to master_tree tips, and
# fossil tips which will also be in the master_tree_tips
#print("print(AC_rowsums_condlikes):")
#print(sum(rowSums(condlikes) == 0))
#print("print(AC_relative_probs_of_each_state_at_branch_bottom_below_node_DOWNPASS_TABLE):")
#print(sum(rowSums(relative_probs_of_each_state_at_branch_bottom_below_node_DOWNPASS_TABLE) == 0))
downpass_condlikes_at_branch_top = get_tip_likelihoods_of_subbranch_from_resCondlikes_given_master_table(stratum=stratum, piecenum=piecenum, master_table=master_table, condlikes=condlikes, relative_probs_of_each_state_at_branch_bottom_below_node_DOWNPASS_TABLE=relative_probs_of_each_state_at_branch_bottom_below_node_DOWNPASS_TABLE)
# really these are downpass relprobs, but whatever
# Normalize just to make sure
#print("print(AC_downpass_condlikes_at_branch_top):")
#print(downpass_condlikes_at_branch_top)
downpass_relprobs_at_branch_top = downpass_condlikes_at_branch_top / sum(downpass_condlikes_at_branch_top)
# if (master_nodenum == 36)
# {
# print(downpass_relprobs_at_branch_top)
# }
# Now you just need to exponentiate up, given the previous-done
# independent likelihoods
condprobs_branch_top = rep(0, times=numstates)
condprobs_branch_bot = rep(0, times=numstates)
condprobs_branch_bot[starting_state_1based] = 1
# 2017-04-06_error check
if (sum(condprobs_branch_bot) == 0)
{
txt = "STOP ERROR BB1: sum(condprobs_branch_bot) == 0. Printing starting_state_1based of condprobs_branch_bot[starting_state_1based] = 1:"
cat("\n\n")
print(txt)
print("print(starting_state_1based):")
print(starting_state_1based)
cat("\n\n")
stop(txt)
}
# HERE
if (stochastic_mapping_inputs$store_stratum_states_list_TF == FALSE)
{
# Exponentiate up (well, sorta, exponential pre-calculated)
condprobs_branch_top = condprobs_branch_bot %*% independent_likelihoods_by_tree_piece_for_timeperiod_i[[piecenum]]
}
if (stochastic_mapping_inputs$store_stratum_states_list_TF == TRUE)
{
indlikes_subset = independent_likelihoods_by_tree_piece_for_timeperiod_i[[piecenum]]
subset_nums = (1:length(stochastic_mapping_inputs$states_allowed_this_timeperiod_TF))[stochastic_mapping_inputs$states_allowed_this_timeperiod_TF]
condprobs_branch_top_subset = condprobs_branch_bot[subset_nums]
condprobs_branch_top_subset = condprobs_branch_top_subset %*% indlikes_subset
condprobs_branch_top = rep(0, times=length(stochastic_mapping_inputs$states_allowed_this_timeperiod_TF))
condprobs_branch_top[subset_nums] = condprobs_branch_top_subset
# Expand the subset Qmat to be full-size
Qmat_big = matrix(data=0, nrow=length(stochastic_mapping_inputs$states_allowed_this_timeperiod_TF), ncol=length(stochastic_mapping_inputs$states_allowed_this_timeperiod_TF))
Qmat_big[subset_nums,subset_nums] = Qmat
}
# zero out the NULL range, since it is impossible in a survivor
# 2021-06-22_NJM allow null tips means, possibly, sister groups with null ranges
# (at least, Michael Nicolai has this)
dont_zero_out_nulls = TRUE
if ( (res$inputs$include_null_range == TRUE) && (res$inputs$allow_null_tips == FALSE) && (dont_zero_out_nulls==TRUE))
{
condprobs_branch_top[1] = 0 # zero out the NULL range, since it is impossible in a survivor
} # END if (res$inputs$include_null_range == TRUE)
# State probabilities at the top of the branch
#print("print(AD_condprobs_branch_top):")
#print(condprobs_branch_top)
#print("print(AD_downpass_relprobs_at_branch_top):")
#print(downpass_relprobs_at_branch_top)
# 2019-04-29 error check
# Check if it's a fossil tip in the correct stratum. If not, treat like normal.
# If so, skip and set probs_branch_top=downpass_relprobs_at_branch_top
# (pass down the branch likelihoods)
time_top = res$inputs$master_table$time_top[rownum_master_table]
time_bot = res$inputs$master_table$time_bot[rownum_master_table]
time_bp = res$inputs$master_table$time_bp[rownum_master_table]
timebin_TF1 = time_bp >= time_top
timebin_TF2 = time_bp < time_bot
fossil_tip_inside_timebin_TF = (timebin_TF1 + timebin_TF2) == 2
# 2023-06-21 - bug check
if (fossil_tip_inside_timebin_TF == FALSE)
{
#print(TRUE)
probs_branch_top = condprobs_branch_top * downpass_relprobs_at_branch_top
probs_branch_top = probs_branch_top / sum(probs_branch_top)
}
if (fossil_tip_inside_timebin_TF == TRUE)
{
#print(FALSE)
probs_branch_top = downpass_relprobs_at_branch_top
}
# Sample the state
treepiece_seed_counter = treepiece_seed_counter + 1
seedval = seedval + (treepiece_seed_counter * treepiece_seed_counter_increment)
if (seedval > 2147483647)
{
seedval = seedval %% 2147483647
}
set.seed(seed=seedval)
#print("print(AD_probs_branch_top):")
#printall(probs_branch_top)
sampled_state_branch_top_1based = sample(x=1:numstates, size=1, replace=TRUE, prob=probs_branch_top)
sampled_state_branch_top_1based
# ERROR CHECK
print_big_error_check = FALSE
if (isblank_TF(sampled_state_branch_top_1based) == TRUE)
{
print_big_error_check = TRUE
}
if (print_big_error_check == TRUE)
{
txt = paste0("\n\nSTOP ERROR123 AFTER 'sampled_state_branch_top_1based = sample(x=1:numstates, size=1, replace=TRUE, prob=probs_branch_top)'\n\n")
cat(txt)
print("timeperiod_i")
print(timeperiod_i)
print("stratum")
print(stratum)
print("piecenum")
print(piecenum)
print("rownum")
print(rownum)
print("master_table_timeperiod_i")
printall(master_table_timeperiod_i)
print("master_table_timeperiod_i[subtable_rownum,]")
print(master_table_timeperiod_i[subtable_rownum,])
print("subtable_rownum")
print(subtable_rownum)
print("dim(master_table_timeperiod_i)")
print(dim(master_table_timeperiod_i))
print("rownum")
print(rownum)
print("condprobs_branch_top")
print(condprobs_branch_top)
print("downpass_relprobs_at_branch_top")
print(downpass_relprobs_at_branch_top)
print("probs_branch_top")
printall(probs_branch_top)
print("sampled_state_branch_top_1based")
print(sampled_state_branch_top_1based)
stop(txt)
} # END if (print_big_error_check) == TRUE
# Store the state
master_table_timeperiod_i$sampled_states_AT_nodes[subtable_rownum] = sampled_state_branch_top_1based
# Also, put the state at the branch bottom of the next stratum up
# (as long as you're not in the top stratum)
if (timeperiod_i != 1)
{
# 1 stratum up:
timeperiod_i_up = timeperiod_i - 1
stochastic_mapping_inputs_up = stochastic_mapping_inputs_list[[timeperiod_i_up]]
master_table_timeperiod_i_up = stochastic_mapping_inputs_up$master_table_timeperiod_i
tree_sections_up = stochastic_mapping_inputs_up$tree_sections_list
# Current stratum
node_at_top_of_branch = master_table_timeperiod_i$node[subtable_rownum]
# Find the node at the branch top (which could be in the stratum above,
# or even higher, no worries, they all have the same node at the top)
node_above_TF = master_table_timeperiod_i_up$node == node_at_top_of_branch
rownum_above = (1:nrow(master_table_timeperiod_i_up))[node_above_TF]
rownum_above
# This is the row for the node at the top of the branch
# (or equivalent branch section in the stratum above)
# master_table_timeperiod_i_up[rownum_above,]
# Store the (now known) ancestral state at the bottom of the branch
master_table_timeperiod_i_up$sampled_states_AT_brbots[rownum_above] = sampled_state_branch_top_1based
# Put these back into the master tables
# Store the node in the stratum above
stochastic_mapping_inputs_list[[timeperiod_i_up]]$master_table_timeperiod_i = master_table_timeperiod_i_up
} # END if (timeperiod_i != 1)
# Simulate a history along the branch, given the starting and
# ending states
# Stochastic map on a sub-branch
treepiece_seed_counter = treepiece_seed_counter + 1
seedval = seedval + (treepiece_seed_counter * treepiece_seed_counter_increment)
# Correction for seeds over the integer max
if (seedval > 2147483647)
{
seedval = seedval %% 2147483647
}
set.seed(seed=seedval)
#######################################################
# 2016-05-07_bugfix
#######################################################
#print(seedval)
#print(timeperiod_i)
#print(piecenum)
# seedval = 27579383
# timeperiod_i = 1
# piecenum = 10
# print(seedval)
# print(timeperiod_i)
# print(piecenum)
#
# nodenum_at_top_of_branch=subtable_rownum;
# trtable=master_table_timeperiod_i;
# Qmat;
# state_indices_0based;
# ranges_list;
# areas;
# single_branch=single_branch;
# stratified=stratified;
# maxtries=maxtries
# manual_history_for_difficult_branches=TRUE
# Check for branches where the tips are BELOW the time-bin!
branch_top_full_tree = master_table_timeperiod_i$time_bp[subtable_rownum]
branch_bot_full_tree = master_table_timeperiod_i$time_bp[subtable_rownum] - master_table_timeperiod_i$edge.length[subtable_rownum]
branch_length_full_tree = master_table_timeperiod_i$edge.length[subtable_rownum]
# The SUBedge.length produced by tree sectioning; MAY INCLUDE FAKE BRANCH LENGTH!!
branch_length_subsection = master_table_timeperiod_i$SUBedge.length[subtable_rownum]
#cat("\nABC1_stochastic_map_given_inputs():\n")
if (branch_length_subsection > branch_length_full_tree)
{
events_table_for_branch = NULL
} else {
if (stochastic_mapping_inputs$store_stratum_states_list_TF == FALSE)
{
events_table_for_branch = stochastic_map_branch(nodenum_at_top_of_branch=subtable_rownum, trtable=master_table_timeperiod_i, Qmat, state_indices_0based, ranges_list, areas, single_branch=single_branch, stratified=stratified, maxtries=maxtries, manual_history_for_difficult_branches=TRUE)
}
if (stochastic_mapping_inputs$store_stratum_states_list_TF == TRUE)
{
events_table_for_branch = stochastic_map_branch(nodenum_at_top_of_branch=subtable_rownum, trtable=master_table_timeperiod_i, Qmat=Qmat_big, state_indices_0based, ranges_list, areas, single_branch=single_branch, stratified=stratified, maxtries=maxtries, manual_history_for_difficult_branches=TRUE)
}
} # END if (branch_length_subsection > branch_length_full_tree)
#cat("\nABC2_stochastic_map_given_inputs():\n")
# Convert the events to text
branch_events_txt = events_table_into_txt(events_table_for_branch)
branch_events_txt
#cat("\nABC3_stochastic_map_given_inputs():\n")
# Store the node history in the current stratum
master_table_timeperiod_i$anagenetic_events_txt_below_node[subtable_rownum] = branch_events_txt
# Store the updated subtable
stochastic_mapping_inputs$master_table_timeperiod_i = master_table_timeperiod_i
# Make sure it's in the global data structure
stochastic_mapping_inputs_list[[timeperiod_i]]$master_table_timeperiod_i = master_table_timeperiod_i
#cat("\nABC4_stochastic_map_given_inputs():\n")
#print("print(piecenum):")
#print(piecenum)
#print("print(timeperiod_i):")
#print(timeperiod_i)
# End stochastic mapping on a branch
} else {
#######################################################
#######################################################
# Stochastically map on sub-tree (not a single branch)
#######################################################
#######################################################
# Piece is a subtree; stochastically map on that subtree,
# STARTING FROM THE ROOT BRANCH
# timeperiod_i = 5
# piecenum = 1
# stochastic_mapping_inputs = stochastic_mapping_inputs_list[[timeperiod_i]]
# master_table_timeperiod_i = stochastic_mapping_inputs$master_table_timeperiod_i
# tree_sections_list = stochastic_mapping_inputs$tree_sections_list
# tree_pieces = tree_sections_list$return_pieces_list
# num_pieces = length(tree_pieces)
# tree_piece = tree_pieces[[piecenum]]
txt = paste("timeperiod_i= ", timeperiod_i, ", piecenum=", piecenum, sep="")
#("\n")
#cat(txt)
# Find the root node of the subtree
contains_rootTF = master_table_timeperiod_i$SUBnode.type == "root"
sub_piecenumTF = master_table_timeperiod_i$piecenum == piecenum
sub_rootTF = (contains_rootTF + sub_piecenumTF) == 2
# Error check
if (sum(sub_rootTF) != 1)
{
errortxt = paste("\n\nERROR: subtree table must have a single node of SUBnode.type=='root'.\nPrinting subtree table:\n\n", sep="")
cat(errortxt)
print(master_table_timeperiod_i)
stop("\nStopping on error.\n")
}
# Get the row number in the subtable
subtable_rownum = (1:nrow(master_table_timeperiod_i))[sub_rootTF]
# Check if there is a branch below the root node
# (unless it's the global root, in which case, ignore)
rootedge = FALSE
if (master_table_timeperiod_i$node.type[subtable_rownum] == "root")
{
# It's the root of the full tree, so *NO* root edge below
rootedge = FALSE
} else {
if ( (!is.na(master_table_timeperiod_i$edge.length[subtable_rownum])) && (!is.na(master_table_timeperiod_i$sampled_states_AT_brbots[subtable_rownum])) )
{
rootedge = TRUE
}
}
#print(rootedge)
stochastic_mapping_inputs$rootedge = rootedge
# Stochastically map
stochastic_mapping_inputs$master_table_timeperiod_i = master_table_timeperiod_i
#cat("\n\nTrying stochastic mapping on subtree:\n\n")
treepiece_seed_counter = treepiece_seed_counter + 1
seedval = seedval + (treepiece_seed_counter * treepiece_seed_counter_increment)
if (seedval > 2147483647)
{
seedval = seedval %% 2147483647
}
set.seed(seed=seedval)
# Here, we can just use res$condlikes, since for subtrees, the node downpass likelihoods are
# for branch tops
# if (any(is.na(master_table_timeperiod_i$sampled_states_AT_nodes)))
# {
# txt = paste0("STOP ERROR_line1469 in (): Some of master_table_timeperiod_i$sampled_states_AT_nodes are NA. Specifically, these:")
# cat("\n\n")
# cat(txt)
# print("print( (1:length(master_table_timeperiod_i$sampled_states_AT_nodes))[is.na(master_table_timeperiod_i$sampled_states_AT_nodes)] )")
#
# print( (1:length(master_table_timeperiod_i$sampled_states_AT_nodes))[is.na(master_table_timeperiod_i$sampled_states_AT_nodes)] )
# print("timeperiod_i")
# print(timeperiod_i)
#
# print("piecenum")
# print(piecenum)
#
# cat("\n\n")
# stop(txt)
# }
#cat("\nA_stochastic_map_given_inputs():\n")
master_table_timeperiod_i = stochastic_map_given_inputs(stochastic_mapping_inputs, piecenum=piecenum, maxtries=maxtries, seedval=seedval, include_null_range=res$inputs$include_null_range, master_nodenum_toPrint=master_nodenum_toPrint, allow_null_tips=res$inputs$allow_null_tips)
#cat("\nB_stochastic_map_given_inputs():\n")
# if (any(is.na(master_table_timeperiod_i$sampled_states_AT_nodes)))
# {
# txt = paste0("STOP ERROR_line1490 in (): Some of master_table_timeperiod_i$sampled_states_AT_nodes are NA. Specifically, these:")
# cat("\n\n")
# cat(txt)
# print("print( (1:length(master_table_timeperiod_i$sampled_states_AT_nodes))[is.na(master_table_timeperiod_i$sampled_states_AT_nodes)] )")
#
# print( (1:length(master_table_timeperiod_i$sampled_states_AT_nodes))[is.na(master_table_timeperiod_i$sampled_states_AT_nodes)] )
# print("timeperiod_i")
# print(timeperiod_i)
#
# print("piecenum")
# print(piecenum)
#
# cat("\n\n")
# stop(txt)
# }
#cat("\n\nEnding stochastic mapping on subtree:\n\n")
# Store the subtable back in inputs
stochastic_mapping_inputs$master_table_timeperiod_i = master_table_timeperiod_i
# Save the result in the list of inputs
stochastic_mapping_inputs_list[[timeperiod_i]] = stochastic_mapping_inputs
#######################################################
# AND, we HAVE to copy up the simulated states to the timeperiod_i above
#######################################################
if (timeperiod_i != 1)
{
# 1 stratum up:
timeperiod_i_up = timeperiod_i - 1
stochastic_mapping_inputs_up = stochastic_mapping_inputs_list[[timeperiod_i_up]]
master_table_timeperiod_i_up = stochastic_mapping_inputs_up$master_table_timeperiod_i
# Find the nodes at the branch tops of the left and right branches
# (which could be in the stratum above,
# or even higher, no worries, they all have the same node at the top)
rows_w_correct_piecenum_TF = master_table_timeperiod_i$piecenum == piecenum
rows_w_tips_TF = master_table_timeperiod_i$SUBnode.type == "tip"
rows_w_subtree_tips_TF = (rows_w_correct_piecenum_TF + rows_w_tips_TF) == 2
rownums_subtree_tips = (1:nrow(master_table_timeperiod_i))[rows_w_subtree_tips_TF]
for (subtree_tipnum in rownums_subtree_tips)
{
#print(subtree_tipnum)
# Get the global node number of this subtree tip
desc_node_node_master_tree = master_table_timeperiod_i$node[subtree_tipnum]
# Get the rownum of this global node number in the
# stratum up
row_timeperiod_i_up_TF = master_table_timeperiod_i_up$node == desc_node_node_master_tree
rownum_timeperiod_i_up = (1:nrow(master_table_timeperiod_i_up))[row_timeperiod_i_up_TF]
# Store the known descendant state at the branch bottom
# in the next stratum up
sampled_state_AT_brbot = master_table_timeperiod_i$sampled_states_AT_nodes[subtree_tipnum]
if (isblank_TF(sampled_state_AT_brbot))
{
txt = paste0("STOP ERROR_line1514 in (): sampled_state_AT_brbot is blank: '", sampled_state_AT_brbot, "'\n\nrownum_timeperiod_i_up=", rownum_timeperiod_i_up, ".\n\nsubtree_tipnum=", subtree_tipnum, ".")
stop(txt)
}
master_table_timeperiod_i_up$sampled_states_AT_brbots[rownum_timeperiod_i_up] = sampled_state_AT_brbot
if (isblank_TF(sampled_state_AT_brbot))
{
txt = paste0("STOP ERROR_line1520 in (): master_table_timeperiod_i_up$sampled_states_AT_brbots[rownum_timeperiod_i_up] is blank: '", master_table_timeperiod_i_up$sampled_states_AT_brbots[rownum_timeperiod_i_up], "'\n\nrownum_timeperiod_i_up=", rownum_timeperiod_i_up, ".\n\nsubtree_tipnum=", subtree_tipnum, ".")
stop(txt)
}
} # END for (subtree_tipnum in rownums_subtree_tips)
# This is the row for the node at the top of the branch
# (or equivalent branch section in the stratum above)
# master_table_timeperiod_i_up[rownum_above,]
# Store the (now known) ancestral state at the bottom of the branches
# in the stratum above
# Store the node in the stratum above
stochastic_mapping_inputs_list[[timeperiod_i_up]]$master_table_timeperiod_i = master_table_timeperiod_i_up
} # END if (timeperiod_i != 1)
} # END if (is.numeric(tree_piece))
} # END for (piecenum in 1:num_pieces)
} # END for (timeperiod_i in num_timeperiods:1)
cat("\nFINISHED_stochastic_mapping_on_stratified()\n")
# Display the stochastic mapping results
master_table_w_stochastic_maps = NULL
for (i in 1:length(stochastic_mapping_inputs_list))
{
master_table_w_stochastic_maps = rbind(master_table_w_stochastic_maps, stochastic_mapping_inputs_list[[i]]$master_table_timeperiod_i)
}
#printall(master_table_w_stochastic_maps[,-ncol(master_table_w_stochastic_maps)])
dim(master_table_w_stochastic_maps)
# Get the anagenetic events in a nice text form
#print("print(master_table_w_stochastic_maps$anagenetic_events_txt_below_node):")
#print(master_table_w_stochastic_maps$anagenetic_events_txt_below_node)
trtable_rownums_of_events_txt = 1:nrow(master_table_w_stochastic_maps)
# events_txt_list=master_table_w_stochastic_maps$anagenetic_events_txt_below_node; trtable=master_table_w_stochastic_maps; trtable_rownums_of_events_txt=trtable_rownums_of_events_txt
ana_events_table = events_txt_list_into_events_table(events_txt_list=master_table_w_stochastic_maps$anagenetic_events_txt_below_node, trtable=master_table_w_stochastic_maps, trtable_rownums_of_events_txt=trtable_rownums_of_events_txt)
#print(events_table)
stochastic_mapping_results = NULL
stochastic_mapping_results$master_table_cladogenetic_events = master_table_w_stochastic_maps
#print(master_table_w_stochastic_maps)
stochastic_mapping_results$table_w_anagenetic_events = ana_events_table
return(stochastic_mapping_results)
} # END stochastic_mapping_on_stratified()
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.