diff --git a/core/species.cpp b/core/species.cpp index 9aec81ae..df2a05f9 100644 --- a/core/species.cpp +++ b/core/species.cpp @@ -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! } @@ -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)