Skip to content
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
113 changes: 28 additions & 85 deletions core/species.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8790,51 +8790,19 @@ void Species::DerivedStatesFromMetadata(tsk_table_collection_t *p_tables)
assert(mutation_table.metadata != nullptr);
assert(mutation_table.metadata_offset != nullptr);

// Swap the derived state column and the metadata column; after this, binary derived states will be in the
// derived state column and ASCII derived states will be in the metadata column.
std::swap(mutation_table.derived_state_length, mutation_table.metadata_length);
std::swap(mutation_table.max_derived_state_length, mutation_table.max_metadata_length);
std::swap(mutation_table.max_derived_state_length_increment, mutation_table.max_metadata_length_increment);
std::swap(mutation_table.derived_state, mutation_table.metadata);
std::swap(mutation_table.derived_state_offset, mutation_table.metadata_offset);

// Then empty out the metadata column, which we don't use while simulating; we want to free up the buffer
// for the metadata, rather than having the (perhaps large capacity) buffer hanging around forever. The
// best way to do this without using (much) private information is to (a) init a new mutation table,
// (b) use tsk_mutation_table_takeset_columns() to set up that table with our number of rows but with
// empty metadata (setting up whatever internal representation our version of tskit prefers for that),
// (c) swap that empty metadata column in to our mutation table, (d) free the metadata column info from the
// temporary mutation table (which now contains the old ASCII derived states), and then (e) let that mutation
// table go WITHOUT tsk_mutation_table_free(). (It will have pointers to all the same buffers as our own
// mutation table, so we don't want to free it!)
tsk_mutation_table_t temp_mutation_table;

tsk_mutation_table_init(&temp_mutation_table, 0);
tsk_mutation_table_takeset_columns(&temp_mutation_table,
mutation_table.num_rows,
mutation_table.site,
mutation_table.node,
mutation_table.parent,
mutation_table.time,
mutation_table.derived_state,
mutation_table.derived_state_offset,
/* metadata */ NULL,
/* metadata_offset */ NULL);

std::swap(temp_mutation_table.metadata_length, mutation_table.metadata_length);
std::swap(temp_mutation_table.max_metadata_length, mutation_table.max_metadata_length);
std::swap(temp_mutation_table.max_metadata_length_increment, mutation_table.max_metadata_length_increment);
std::swap(temp_mutation_table.metadata, mutation_table.metadata);
std::swap(temp_mutation_table.metadata_offset, mutation_table.metadata_offset);

// WE DO NOT DO:
// tsk_mutation_table_free(&temp_mutation_table);
// INSTEAD WE DO:
tsk_safe_free(temp_mutation_table.metadata); // free the old ASCII derived state data
tsk_safe_free(temp_mutation_table.metadata_offset); // free the offsets for that old data
tsk_safe_free(temp_mutation_table.metadata_schema); // free the schema from tsk_mutation_table_init()
// AND THEN WE JUST LET IT GO OUT OF SCOPE AND DISAPPEAR.

// Put the metadata column in the derived state column; after this, binary derived states
// will be in the derived state column. Empty out the derived state column, which we don't use while simulating;
// we want to free up the buffer rather than having the (perhaps large capacity) buffer hanging around forever.
// See tsk_mutation_table_init for how to initialize an empty metadata column.
tsk_safe_free(mutation_table.derived_state);
tsk_safe_free(mutation_table.derived_state_offset);
mutation_table.derived_state = mutation_table.metadata;
mutation_table.derived_state_offset = mutation_table.metadata_offset;
mutation_table.metadata = (char *) tsk_malloc(1);
mutation_table.metadata_offset = (tsk_size_t *) tsk_calloc(mutation_table.num_rows + 1, sizeof(tsk_size_t));
if (!mutation_table.metadata || !mutation_table.metadata_offset)
EIDOS_TERMINATION << "ERROR (Species::DerivedStatesFromMetadata): allocation failed; you may need to raise the memory limit for SLiM." << EidosTerminate(nullptr);

// Of course the above code will need to be updated if tskit's mutation table implementation changes!
}

Expand Down Expand Up @@ -8880,51 +8848,26 @@ void Species::DerivedStatesToMetadata(tsk_table_collection_t *p_tables)
}

tsk_size_t metadata_size = text_derived_state.size() * sizeof(char);
tsk_size_t metadata_offset_size = (mutation_table.num_rows + 1) * sizeof(tsk_size_t);
char *new_metadata_buffer = (char *)malloc(metadata_size);
if (!new_metadata_buffer)
tsk_size_t *new_metadata_offset_buffer = (tsk_size_t *)malloc(metadata_offset_size);
if (!new_metadata_buffer || !new_metadata_offset_buffer)
EIDOS_TERMINATION << "ERROR (Species::DerivedStatesToMetadata): allocation failed; you may need to raise the memory limit for SLiM." << EidosTerminate(nullptr);

memcpy(new_metadata_buffer, text_derived_state.c_str(), metadata_size);
memcpy(new_metadata_offset_buffer, text_derived_state_offset, metadata_offset_size);


// Now we want to toss any existing metadata column and put this new metadata column data in its place. The
// best way to do this without using (much) private information is to (a) init a new mutation table, (b) use
// tsk_mutation_table_takeset_columns() to set up that table with all our existing columns but with the new
// metadata column, (c) swap its representation of the new metadata column back into our own table, and
// (d) let the temporary mutation table go WITHOUT tsk_mutation_table_free(). (It will have pointers to
// all the same buffers as our own mutation table, so we don't want to free it!)
tsk_mutation_table_t temp_mutation_table;

tsk_mutation_table_init(&temp_mutation_table, 0);
tsk_mutation_table_takeset_columns(&temp_mutation_table,
mutation_table.num_rows,
mutation_table.site,
mutation_table.node,
mutation_table.parent,
mutation_table.time,
mutation_table.derived_state,
mutation_table.derived_state_offset,
/* metadata */ new_metadata_buffer,
/* metadata_offset */ text_derived_state_offset);

std::swap(temp_mutation_table.metadata_length, mutation_table.metadata_length);
std::swap(temp_mutation_table.max_metadata_length, mutation_table.max_metadata_length);
std::swap(temp_mutation_table.max_metadata_length_increment, mutation_table.max_metadata_length_increment);
std::swap(temp_mutation_table.metadata, mutation_table.metadata);
std::swap(temp_mutation_table.metadata_offset, mutation_table.metadata_offset); // identical already, actually

// WE DO NOT DO:
// tsk_mutation_table_free(&temp_mutation_table);
// INSTEAD WE DO:
tsk_safe_free(temp_mutation_table.metadata_schema); // free the schema from tsk_mutation_table_init()
// AND THEN WE JUST LET IT GO OUT OF SCOPE AND DISAPPEAR.

// Finally, swap the derived state column and the metadata column; after this, binary derived states
// will be in the metadata column, and ASCII derived states will be in the derived state column.
std::swap(mutation_table.derived_state_length, mutation_table.metadata_length);
std::swap(mutation_table.max_derived_state_length, mutation_table.max_metadata_length);
std::swap(mutation_table.max_derived_state_length_increment, mutation_table.max_metadata_length_increment);
std::swap(mutation_table.derived_state, mutation_table.metadata);
std::swap(mutation_table.derived_state_offset, mutation_table.metadata_offset);
// Now we want to toss any existing metadata column and put this new metadata column data in its place.
tsk_safe_free(mutation_table.metadata);
tsk_safe_free(mutation_table.metadata_offset);
mutation_table.metadata = mutation_table.derived_state;
mutation_table.metadata_offset = mutation_table.derived_state_offset;
mutation_table.derived_state = new_metadata_buffer;
mutation_table.derived_state_offset = new_metadata_offset_buffer;
for (size_t j = 0; j < mutation_table.num_rows; j++) {
std::cout << mutation_table.derived_state_offset[j] << ", " << mutation_table.metadata_offset[j] << std::endl;
}
}

void Species::AddIndividualsToTable(Individual * const *p_individual, size_t p_num_individuals, tsk_table_collection_t *p_tables, INDIVIDUALS_HASH *p_individuals_hash, tsk_flags_t p_flags)
Expand Down
Loading