Program Listing for File Metacommunity.cpp¶
↰ Return to documentation for file (necsim/Metacommunity.cpp
)
// This file is part of necsim project which is released under MIT license.
// See file **LICENSE.txt** or visit https://opensource.org/licenses/MIT) for full license details.
#include <utility>
#include <unordered_map>
#include "Metacommunity.h"
#include "neutral_analytical.h"
#include "LogFile.h"
#include "SpeciesAbundancesHandler.h"
#include "SimulatedSpeciesAbundancesHandler.h"
#include "AnalyticalSpeciesAbundancesHandler.h"
namespace na = neutral_analytical;
namespace necsim
{
Metacommunity::Metacommunity() : seed(0), job_type(0), parameters_checked(false),
species_abundances_handler(make_unique<SimulatedSpeciesAbundancesHandler>()),
random(make_shared<RNGController>()), metacommunity_tree(make_unique<Tree>())
{
}
void Metacommunity::setCommunityParameters(shared_ptr<MetacommunityParameters> metacommunity_parameters)
{
current_metacommunity_parameters = std::move(metacommunity_parameters);
// Check if no metacommunity option has been supplied - in which case use sensible defaults
if(current_metacommunity_parameters->option == "none" || current_metacommunity_parameters->option == "null")
{
// Simulate only for smaller community sizes
if(current_metacommunity_parameters->metacommunity_size > 1000)
{
current_metacommunity_parameters->option = "analytical";
}
else
{
current_metacommunity_parameters->option = "simulated";
}
}
}
void Metacommunity::checkSimulationParameters()
{
if(!parameters_checked)
{
if(!database->isOpen())
{
throw FatalException("Cannot read simulation metacommunity parameters as database is null pointer.");
}
// Now do the same for times
string sql_call = "SELECT seed, job_type from SIMULATION_PARAMETERS";
auto stmt = database->prepare(sql_call);
database->step();
seed = sqlite3_column_int64(stmt->stmt, 0);
random->setSeed(seed);
job_type = sqlite3_column_int64(stmt->stmt, 1);
database->finalise();
parameters_checked = true;
}
}
void Metacommunity::addSpecies(unsigned long &species_count, TreeNode* tree_node, set<unsigned long> &species_list)
{
auto species_id = species_abundances_handler->getRandomSpeciesID();
if(species_id == 0)
{
throw FatalException("Obtained species id was 0 in metacommunity application - please report this bug.");
}
if(species_list.empty() || species_list.find(species_id) == species_list.end())
{
species_list.insert(species_id);
species_count++;
}
#ifdef DEBUG
if(tree_node->getSpeciesID() != 0)
{
throw FatalException("Trying to add species for lineages with non-zero species id. Please report this bug.");
}
#endif // DEBUG
tree_node->burnSpecies(species_id);
}
void Metacommunity::createMetacommunityNSENeutralModel()
{
#ifdef DEBUG
writeLog(10, "Running spatially implicit model for metacommunity generation.");
#endif //DEBUG
// First set up a non-spatial coalescence simulation to generate our metacommunity
shared_ptr<SimParameters> temp_parameters = make_shared<SimParameters>();
// Generate a new unique seed by adding 1073741823 if the seed is 0 - this ensures that 0 and 1 never appear as
// random seeds, which cause autocorrelation in simulation outputs.
if(seed == 0)
{
seed = 1073741823;
}
temp_parameters->setMetacommunityParameters(current_metacommunity_parameters->metacommunity_size,
current_metacommunity_parameters->speciation_rate, seed, job_type);
// Dispose of any previous Tree object and create a new one
metacommunity_tree = make_unique<Tree>();
metacommunity_tree->internalSetup(temp_parameters);
// Run our simulation and calculate the species abundance distribution (as this is all that needs to be stored).
if(!metacommunity_tree->runSimulation())
{
throw FatalException("Completion of the non-spatial coalescence simulation "
"to create the metacommunity did not finish in time.");
}
metacommunity_tree->applySpecRateInternal(current_metacommunity_parameters->speciation_rate, 0.0);
// species_abundances now contains the number of individuals per species
// Make it cumulative to increase the speed of indexing using binary search.
species_abundances_handler = make_unique<SimulatedSpeciesAbundancesHandler>();
species_abundances_handler->setup(random, current_metacommunity_parameters->metacommunity_size,
current_metacommunity_parameters->speciation_rate, nodes->size());
auto tmp_species_abundances = metacommunity_tree->getSpeciesAbundances();
if(tmp_species_abundances->empty())
{
throw FatalException("Simulated species abundance list is empty. Please report this bug.");
}
// Remove the 0 at the start
species_abundances_handler->setAbundanceList(tmp_species_abundances);
#ifdef DEBUG
writeLog(10, "Spatially implicit simulation completed.");
#endif //DEBUG
}
void Metacommunity::applyNoOutput(shared_ptr<SpecSimParameters> sp, shared_ptr<vector<TreeNode>> tree_data)
{
#ifdef DEBUG
writeLog(10, "********************");
writeLog(10, "Metacommunity application");
#endif //DEBUG
// Make sure that the connection is opened to file.
if(!bSqlConnection)
{
openSqlConnection(sp->filename);
}
checkSimulationParameters();
for(const auto &item: sp->metacommunity_parameters)
{
setCommunityParameters(item);
printMetacommunityParameters();
setupApplication(sp, tree_data);
if(current_metacommunity_parameters->option == "simulated")
{
createMetacommunityNSENeutralModel();
}
else if(current_metacommunity_parameters->option == "analytical")
{
// Use approximation for the SAD from Chisholm and Pacala (2010)
approximateSAD();
}
else
{
// Use the file path provided
readSAD();
}
#ifdef DEBUG
writeLog(10, "Creating coalescence tree from metacommunity...");
#endif //DEBUG
calculateTree();
}
}
void Metacommunity::approximateSAD()
{
species_abundances_handler.reset();
species_abundances_handler = make_unique<AnalyticalSpeciesAbundancesHandler>();
species_abundances_handler->setup(random, current_metacommunity_parameters->metacommunity_size,
current_metacommunity_parameters->speciation_rate, nodes->size());
}
void Metacommunity::readSAD()
{
Community external_metacommunity;
external_metacommunity.openSqlConnection(current_metacommunity_parameters->option);
shared_ptr<map<unsigned long, unsigned long>> sad = external_metacommunity.getSpeciesAbundances(
current_metacommunity_parameters->external_reference);
species_abundances_handler.reset();
species_abundances_handler = make_unique<SimulatedSpeciesAbundancesHandler>();
species_abundances_handler->setup(random, current_metacommunity_parameters->metacommunity_size,
current_metacommunity_parameters->speciation_rate, nodes->size());
species_abundances_handler->setAbundanceList(sad);
}
void Metacommunity::printMetacommunityParameters()
{
stringstream ss;
ss << "Metacommunity current_metacommunity_parameters:" << endl;
ss << "Metacommunity size: " << current_metacommunity_parameters->metacommunity_size << endl;
ss << "Speciation rate: " << current_metacommunity_parameters->speciation_rate << endl;
ss << "Option: " << current_metacommunity_parameters->option << endl;
ss << "External reference: " << current_metacommunity_parameters->external_reference << endl;
writeInfo(ss.str());
}
}