diff --git a/c/CHANGELOG.rst b/c/CHANGELOG.rst index e15bea52c2..61d8d14f6c 100644 --- a/c/CHANGELOG.rst +++ b/c/CHANGELOG.rst @@ -53,9 +53,11 @@ :pr:`1742`). - Add ``time_units`` to ``tsk_table_collection_t`` to describe the units of the time dimension of the - tree sequence. This is then used to generate an error if ``time_units`` is ``uncalibrated`` when + tree sequence. This is then used to geerate an error if ``time_units`` is ``uncalibrated`` when using the branch lengths in statistics. (:user:`benjeffery`, :issue:`1644`, :pr:`1760`) +- Add reference sequence to table collection (:user:`benjeffery`, :issue:`146`, :pr:`1911`) + - FIXME add features for virtual root, num_edges, stack allocation size etc **Fixes** diff --git a/c/tests/test_tables.c b/c/tests/test_tables.c index 9463d650c3..1c89095f66 100644 --- a/c/tests/test_tables.c +++ b/c/tests/test_tables.c @@ -324,6 +324,254 @@ test_table_collection_simplify_errors(void) tsk_table_collection_free(&tables); } +static void +test_reference_sequence(void) +{ + int ret; + tsk_reference_sequence_t *r1 = NULL; + tsk_reference_sequence_t *r2 = NULL; + + char example_data[100] = "An example string with unicode 🎄🌳🌴🌲🎋"; + tsk_size_t example_data_length = (tsk_size_t) strlen(example_data); + char example_url[100] = "An example url with unicode 🎄🌳🌴🌲🎋"; + tsk_size_t example_url_length = (tsk_size_t) strlen(example_url); + char example_metadata[100] = "An example metadata with unicode 🎄🌳🌴🌲🎋"; + tsk_size_t example_metadata_length = (tsk_size_t) strlen(example_metadata); + char example_schema[100] = "An example schema with unicode 🎄🌳🌴🌲🎋"; + tsk_size_t example_schema_length = (tsk_size_t) strlen(example_schema); + + // Test equality + CU_ASSERT_TRUE(tsk_reference_sequence_equals(r1, r2, 0)); + + r1 = tsk_malloc(sizeof(tsk_reference_sequence_t)); + CU_ASSERT_NOT_EQUAL_FATAL(r1, NULL); + tsk_reference_sequence_init(r1); + + ret = tsk_reference_sequence_set_data(r1, example_data, example_data_length); + CU_ASSERT_EQUAL_FATAL(ret, 0); + CU_ASSERT_FALSE(tsk_reference_sequence_equals(r1, r2, 0)); + + r2 = tsk_malloc(sizeof(tsk_reference_sequence_t)); + CU_ASSERT_NOT_EQUAL_FATAL(r2, NULL); + tsk_reference_sequence_init(r2); + + ret = tsk_reference_sequence_set_data(r1, "", 0); + CU_ASSERT_EQUAL_FATAL(ret, 0); + CU_ASSERT_TRUE(tsk_reference_sequence_equals(r1, r2, 0)); + + ret = tsk_reference_sequence_set_data(r1, example_data, example_data_length); + CU_ASSERT_EQUAL_FATAL(ret, 0); + CU_ASSERT_FALSE(tsk_reference_sequence_equals(r1, r2, 0)); + + ret = tsk_reference_sequence_set_data(r2, example_data, example_data_length); + CU_ASSERT_EQUAL_FATAL(ret, 0); + CU_ASSERT_TRUE(tsk_reference_sequence_equals(r1, r2, 0)); + + ret = tsk_reference_sequence_set_url(r1, example_url, example_url_length); + CU_ASSERT_EQUAL_FATAL(ret, 0); + CU_ASSERT_FALSE(tsk_reference_sequence_equals(r1, r2, 0)); + ret = tsk_reference_sequence_set_url(r2, example_url, example_url_length); + CU_ASSERT_EQUAL_FATAL(ret, 0); + CU_ASSERT_TRUE(tsk_reference_sequence_equals(r1, r2, 0)); + + ret = tsk_reference_sequence_set_metadata( + r1, example_metadata, example_metadata_length); + CU_ASSERT_EQUAL_FATAL(ret, 0); + CU_ASSERT_FALSE(tsk_reference_sequence_equals(r1, r2, 0)); + ret = tsk_reference_sequence_set_metadata( + r2, example_metadata, example_metadata_length); + CU_ASSERT_EQUAL_FATAL(ret, 0); + CU_ASSERT_TRUE(tsk_reference_sequence_equals(r1, r2, 0)); + + ret = tsk_reference_sequence_set_metadata_schema( + r1, example_schema, example_schema_length); + CU_ASSERT_EQUAL_FATAL(ret, 0); + CU_ASSERT_FALSE(tsk_reference_sequence_equals(r1, r2, 0)); + ret = tsk_reference_sequence_set_metadata_schema( + r2, example_schema, example_schema_length); + CU_ASSERT_EQUAL_FATAL(ret, 0); + CU_ASSERT_TRUE(tsk_reference_sequence_equals(r1, r2, 0)); + + // Test copy + tsk_reference_sequence_free(r1); + tsk_safe_free(r1); + r1 = NULL; + tsk_reference_sequence_free(r2); + tsk_safe_free(r2); + r2 = NULL; + + r1 = tsk_malloc(sizeof(tsk_reference_sequence_t)); + CU_ASSERT_NOT_EQUAL_FATAL(r1, NULL); + tsk_reference_sequence_init(r1); + ret = tsk_reference_sequence_set_data(r1, example_data, example_data_length); + CU_ASSERT_EQUAL_FATAL(ret, 0); + ret = tsk_reference_sequence_copy(r1, &r2, 0); + CU_ASSERT_EQUAL_FATAL(ret, 0); + CU_ASSERT_TRUE(tsk_reference_sequence_equals(r1, r2, 0)); + + ret = tsk_reference_sequence_set_url(r1, example_url, example_url_length); + CU_ASSERT_EQUAL_FATAL(ret, 0); + ret = tsk_reference_sequence_copy(r1, &r2, 0); + CU_ASSERT_EQUAL_FATAL(ret, 0); + CU_ASSERT_TRUE(tsk_reference_sequence_equals(r1, r2, 0)); + + ret = tsk_reference_sequence_set_metadata( + r1, example_metadata, example_metadata_length); + CU_ASSERT_EQUAL_FATAL(ret, 0); + ret = tsk_reference_sequence_copy(r1, &r2, 0); + CU_ASSERT_EQUAL_FATAL(ret, 0); + CU_ASSERT_TRUE(tsk_reference_sequence_equals(r1, r2, 0)); + + ret = tsk_reference_sequence_set_metadata_schema( + r1, example_schema, example_schema_length); + CU_ASSERT_EQUAL_FATAL(ret, 0); + ret = tsk_reference_sequence_copy(r1, &r2, 0); + CU_ASSERT_EQUAL_FATAL(ret, 0); + CU_ASSERT_TRUE(tsk_reference_sequence_equals(r1, r2, 0)); + + tsk_reference_sequence_free(r1); + tsk_safe_free(r1); + tsk_reference_sequence_free(r2); + tsk_safe_free(r2); +} + +static void +test_table_collection_reference_sequence(void) +{ + int ret; + tsk_table_collection_t tc1, tc2; + + char example_data[100] = "An example string with unicode 🎄🌳🌴🌲🎋"; + tsk_size_t example_data_length = (tsk_size_t) strlen(example_data); + char example_url[100] = "An example url with unicode 🎄🌳🌴🌲🎋"; + tsk_size_t example_url_length = (tsk_size_t) strlen(example_url); + char example_metadata[100] = "An example metadata with unicode 🎄🌳🌴🌲🎋"; + tsk_size_t example_metadata_length = (tsk_size_t) strlen(example_metadata); + char example_schema[100] = "An example schema with unicode 🎄🌳🌴🌲🎋"; + tsk_size_t example_schema_length = (tsk_size_t) strlen(example_schema); + + // Test equality + ret = tsk_table_collection_init(&tc1, 0); + CU_ASSERT_EQUAL_FATAL(ret, 0); + ret = tsk_table_collection_init(&tc2, 0); + CU_ASSERT_EQUAL_FATAL(ret, 0); + CU_ASSERT_TRUE(tsk_table_collection_equals(&tc1, &tc2, 0)); + + tc1.reference_sequence = tsk_malloc(sizeof(tsk_reference_sequence_t)); + CU_ASSERT_NOT_EQUAL_FATAL(tc1.reference_sequence, NULL); + tsk_reference_sequence_init(tc1.reference_sequence); + + ret = tsk_reference_sequence_set_data( + tc1.reference_sequence, example_data, example_data_length); + CU_ASSERT_EQUAL_FATAL(ret, 0); + CU_ASSERT_FALSE(tsk_table_collection_equals(&tc1, &tc2, 0)); + + tc2.reference_sequence = tsk_malloc(sizeof(tsk_reference_sequence_t)); + CU_ASSERT_NOT_EQUAL_FATAL(tc2.reference_sequence, NULL); + tsk_reference_sequence_init(tc2.reference_sequence); + + ret = tsk_reference_sequence_set_data( + tc2.reference_sequence, example_data, example_data_length); + CU_ASSERT_EQUAL_FATAL(ret, 0); + CU_ASSERT_TRUE(tsk_table_collection_equals(&tc1, &tc2, 0)); + + ret = tsk_reference_sequence_set_url( + tc1.reference_sequence, example_url, example_url_length); + CU_ASSERT_EQUAL_FATAL(ret, 0); + CU_ASSERT_FALSE(tsk_table_collection_equals(&tc1, &tc2, 0)); + ret = tsk_reference_sequence_set_url( + tc2.reference_sequence, example_url, example_url_length); + CU_ASSERT_EQUAL_FATAL(ret, 0); + CU_ASSERT_TRUE(tsk_table_collection_equals(&tc1, &tc2, 0)); + + ret = tsk_reference_sequence_set_metadata( + tc1.reference_sequence, example_metadata, example_metadata_length); + CU_ASSERT_EQUAL_FATAL(ret, 0); + CU_ASSERT_FALSE(tsk_table_collection_equals(&tc1, &tc2, 0)); + ret = tsk_reference_sequence_set_metadata( + tc2.reference_sequence, example_metadata, example_metadata_length); + CU_ASSERT_EQUAL_FATAL(ret, 0); + CU_ASSERT_TRUE(tsk_table_collection_equals(&tc1, &tc2, 0)); + + ret = tsk_reference_sequence_set_metadata_schema( + tc1.reference_sequence, example_schema, example_schema_length); + CU_ASSERT_EQUAL_FATAL(ret, 0); + CU_ASSERT_FALSE(tsk_table_collection_equals(&tc1, &tc2, 0)); + ret = tsk_reference_sequence_set_metadata_schema( + tc2.reference_sequence, example_schema, example_schema_length); + CU_ASSERT_EQUAL_FATAL(ret, 0); + CU_ASSERT_TRUE(tsk_table_collection_equals(&tc1, &tc2, 0)); + + // Test copy + tsk_table_collection_free(&tc1); + tsk_table_collection_free(&tc2); + ret = tsk_table_collection_init(&tc1, 0); + CU_ASSERT_EQUAL_FATAL(ret, 0); + + tc1.reference_sequence = tsk_malloc(sizeof(tsk_reference_sequence_t)); + CU_ASSERT_NOT_EQUAL_FATAL(tc1.reference_sequence, NULL); + tsk_reference_sequence_init(tc1.reference_sequence); + + ret = tsk_reference_sequence_set_data( + tc1.reference_sequence, example_data, example_data_length); + CU_ASSERT_EQUAL_FATAL(ret, 0); + ret = tsk_table_collection_copy(&tc1, &tc2, 0); + CU_ASSERT_EQUAL_FATAL(ret, 0); + CU_ASSERT_TRUE(tsk_table_collection_equals(&tc1, &tc2, 0)); + + ret = tsk_reference_sequence_set_url( + tc1.reference_sequence, example_url, example_url_length); + CU_ASSERT_EQUAL_FATAL(ret, 0); + ret = tsk_table_collection_copy(&tc1, &tc2, TSK_NO_INIT); + CU_ASSERT_EQUAL_FATAL(ret, 0); + CU_ASSERT_TRUE(tsk_table_collection_equals(&tc1, &tc2, 0)); + + ret = tsk_reference_sequence_set_metadata( + tc1.reference_sequence, example_metadata, example_metadata_length); + CU_ASSERT_EQUAL_FATAL(ret, 0); + ret = tsk_table_collection_copy(&tc1, &tc2, TSK_NO_INIT); + CU_ASSERT_EQUAL_FATAL(ret, 0); + CU_ASSERT_TRUE(tsk_table_collection_equals(&tc1, &tc2, 0)); + + ret = tsk_reference_sequence_set_metadata_schema( + tc1.reference_sequence, example_schema, example_schema_length); + CU_ASSERT_EQUAL_FATAL(ret, 0); + ret = tsk_table_collection_copy(&tc1, &tc2, TSK_NO_INIT); + CU_ASSERT_EQUAL_FATAL(ret, 0); + CU_ASSERT_TRUE(tsk_table_collection_equals(&tc1, &tc2, 0)); + + // Test dump and load + tsk_table_collection_free(&tc1); + tsk_table_collection_free(&tc2); + ret = tsk_table_collection_init(&tc1, 0); + CU_ASSERT_EQUAL_FATAL(ret, 0); + tc1.sequence_length = 1.0; + + tc1.reference_sequence = tsk_malloc(sizeof(tsk_reference_sequence_t)); + CU_ASSERT_NOT_EQUAL_FATAL(tc1.reference_sequence, NULL); + tsk_reference_sequence_init(tc1.reference_sequence); + + ret = tsk_reference_sequence_set_data( + tc1.reference_sequence, example_data, example_data_length); + CU_ASSERT_EQUAL_FATAL(ret, 0); + ret = tsk_reference_sequence_set_url( + tc1.reference_sequence, example_url, example_url_length); + CU_ASSERT_EQUAL_FATAL(ret, 0); + ret = tsk_reference_sequence_set_metadata( + tc1.reference_sequence, example_metadata, example_metadata_length); + CU_ASSERT_EQUAL_FATAL(ret, 0); + ret = tsk_reference_sequence_set_metadata_schema( + tc1.reference_sequence, example_schema, example_schema_length); + CU_ASSERT_EQUAL_FATAL(ret, 0); + ret = tsk_table_collection_dump(&tc1, _tmp_file_name, 0); + CU_ASSERT_EQUAL_FATAL(ret, 0); + ret = tsk_table_collection_load(&tc2, _tmp_file_name, 0); + CU_ASSERT_EQUAL_FATAL(ret, 0); + CU_ASSERT_TRUE(tsk_table_collection_equals(&tc1, &tc2, 0)); + tsk_table_collection_free(&tc1); + tsk_table_collection_free(&tc2); +} + static void test_table_collection_metadata(void) { @@ -8794,7 +9042,11 @@ main(int argc, char **argv) { "test_table_collection_simplify_errors", test_table_collection_simplify_errors }, { "test_table_collection_time_units", test_table_collection_time_units }, + { "test_table_collection_reference_sequence", + test_table_collection_reference_sequence }, { "test_table_collection_metadata", test_table_collection_metadata }, + { "test_reference_sequence", test_reference_sequence }, + { "test_simplify_tables_drops_indexes", test_simplify_tables_drops_indexes }, { "test_simplify_empty_tables", test_simplify_empty_tables }, { "test_simplify_metadata", test_simplify_metadata }, diff --git a/c/tskit/tables.c b/c/tskit/tables.c index f63bb1a1b6..8ce23d7823 100644 --- a/c/tskit/tables.c +++ b/c/tskit/tables.c @@ -626,6 +626,133 @@ write_metadata_schema_header( return fprintf(out, fmt, (int) metadata_schema_length, metadata_schema); } +/************************* + * reference sequence + *************************/ + +int +tsk_reference_sequence_init(tsk_reference_sequence_t *self) +{ + tsk_memset(self, 0, sizeof(*self)); + return 0; +} + +int +tsk_reference_sequence_free(tsk_reference_sequence_t *self) +{ + tsk_safe_free(self->data); + tsk_safe_free(self->url); + tsk_safe_free(self->metadata); + tsk_safe_free(self->metadata_schema); + return 0; +} + +bool +tsk_reference_sequence_equals(const tsk_reference_sequence_t *self, + const tsk_reference_sequence_t *other, tsk_flags_t options) +{ + if (self == NULL && other == NULL) { + return true; + } + /* If one or the other is NULL they are not equal */ + if ((self == NULL) != (other == NULL)) { + return false; + } + return ( + (self->data_length == other->data_length && self->url_length == other->url_length + && ((options & TSK_CMP_IGNORE_TS_METADATA) + || self->metadata_length == other->metadata_length) + && ((options & TSK_CMP_IGNORE_TS_METADATA) + || self->metadata_schema_length == other->metadata_schema_length) + && tsk_memcmp(self->data, other->data, self->data_length * sizeof(char)) == 0 + && tsk_memcmp(self->url, other->url, self->url_length * sizeof(char)) == 0 + && ((options & TSK_CMP_IGNORE_TS_METADATA) + || tsk_memcmp(self->metadata, other->metadata, + self->metadata_length * sizeof(char)) + == 0) + && ((options & TSK_CMP_IGNORE_TS_METADATA) + || tsk_memcmp(self->metadata_schema, other->metadata_schema, + self->metadata_schema_length * sizeof(char)) + == 0))); +} + +int +tsk_reference_sequence_copy(const tsk_reference_sequence_t *self, + tsk_reference_sequence_t **dest, tsk_flags_t TSK_UNUSED(options)) +{ + int ret = 0; + + if (*dest != NULL) { + tsk_reference_sequence_free(*dest); + tsk_safe_free(*dest); + *dest = NULL; + } + + if (self != NULL) { + *dest = tsk_malloc(sizeof(tsk_reference_sequence_t)); + if (*dest == NULL) { + ret = TSK_ERR_NO_MEMORY; + goto out; + } + tsk_reference_sequence_init(*dest); + + ret = tsk_reference_sequence_set_data(*dest, self->data, self->data_length); + if (ret != 0) { + goto out; + } + ret = tsk_reference_sequence_set_url(*dest, self->url, self->url_length); + if (ret != 0) { + goto out; + } + ret = tsk_reference_sequence_set_metadata( + *dest, self->metadata, self->metadata_length); + if (ret != 0) { + goto out; + } + ret = tsk_reference_sequence_set_metadata_schema( + *dest, self->metadata_schema, self->metadata_schema_length); + if (ret != 0) { + goto out; + } + } +out: + return ret; +} + +int +tsk_reference_sequence_set_data(tsk_reference_sequence_t *self, + const char *reference_sequence, tsk_size_t reference_sequence_length) +{ + return replace_string( + &self->data, &self->data_length, reference_sequence, reference_sequence_length); +} + +int +tsk_reference_sequence_set_url(tsk_reference_sequence_t *self, + const char *reference_sequence_url, tsk_size_t reference_sequence_url_length) +{ + return replace_string(&self->url, &self->url_length, reference_sequence_url, + reference_sequence_url_length); +} + +int +tsk_reference_sequence_set_metadata(tsk_reference_sequence_t *self, + const char *reference_sequence_metadata, + tsk_size_t reference_sequence_metadata_length) +{ + return replace_string(&self->metadata, &self->metadata_length, + reference_sequence_metadata, reference_sequence_metadata_length); +} + +int +tsk_reference_sequence_set_metadata_schema(tsk_reference_sequence_t *self, + const char *reference_sequence_metadata_schema, + tsk_size_t reference_sequence_metadata_schema_length) +{ + return replace_string(&self->metadata_schema, &self->metadata_schema_length, + reference_sequence_metadata_schema, reference_sequence_metadata_schema_length); +} + /************************* * individual table *************************/ @@ -9827,6 +9954,10 @@ tsk_table_collection_free(tsk_table_collection_t *self) tsk_mutation_table_free(&self->mutations); tsk_population_table_free(&self->populations); tsk_provenance_table_free(&self->provenances); + if (self->reference_sequence != NULL) { + tsk_reference_sequence_free(self->reference_sequence); + } + tsk_safe_free(self->reference_sequence); tsk_safe_free(self->indexes.edge_insertion_order); tsk_safe_free(self->indexes.edge_removal_order); tsk_safe_free(self->file_uuid); @@ -9876,6 +10007,10 @@ tsk_table_collection_equals(const tsk_table_collection_t *self, && tsk_provenance_table_equals( &self->provenances, &other->provenances, options); } + + ret = ret + && tsk_reference_sequence_equals( + self->reference_sequence, other->reference_sequence, options); return ret; } @@ -10080,6 +10215,11 @@ tsk_table_collection_copy(const tsk_table_collection_t *self, if (ret != 0) { goto out; } + ret = tsk_reference_sequence_copy( + self->reference_sequence, &dest->reference_sequence, options); + if (ret != 0) { + goto out; + } out: return ret; @@ -10295,6 +10435,82 @@ tsk_table_collection_load_indexes(tsk_table_collection_t *self, kastore_t *store return ret; } +static int +tsk_table_collection_load_reference_sequence( + tsk_table_collection_t *self, kastore_t *store) +{ + int ret = 0; + char *data = NULL; + char *url = NULL; + char *metadata = NULL; + char *metadata_schema = NULL; + tsk_size_t data_length = 0, url_length, metadata_length, metadata_schema_length; + bool reference_sequence_loaded; + + read_table_property_t properties[] = { + { "reference_sequence/data", (void **) &data, &data_length, KAS_UINT8, + TSK_COL_OPTIONAL }, + { "reference_sequence/url", (void **) &url, &url_length, KAS_UINT8, + TSK_COL_OPTIONAL }, + { "reference_sequence/metadata", (void **) &metadata, &metadata_length, + KAS_UINT8, TSK_COL_OPTIONAL }, + { "reference_sequence/metadata_schema", (void **) &metadata_schema, + &metadata_schema_length, KAS_UINT8, TSK_COL_OPTIONAL }, + { .name = NULL }, + }; + + ret = read_table_properties(store, properties, 0); + if (ret != 0) { + goto out; + } + reference_sequence_loaded + = data != NULL || url != NULL || metadata != NULL || metadata_schema != NULL; + if (self->reference_sequence != NULL) { + tsk_reference_sequence_free(self->reference_sequence); + tsk_safe_free(self->reference_sequence); + } + if (reference_sequence_loaded) { + self->reference_sequence = tsk_malloc(sizeof(tsk_reference_sequence_t)); + if (self->reference_sequence == NULL) { + ret = TSK_ERR_NO_MEMORY; + goto out; + } + tsk_reference_sequence_init(self->reference_sequence); + } + if (data != NULL) { + ret = tsk_reference_sequence_set_data( + self->reference_sequence, data, (tsk_size_t) data_length); + if (ret != 0) { + goto out; + } + } + if (metadata != NULL) { + ret = tsk_reference_sequence_set_metadata( + self->reference_sequence, metadata, (tsk_size_t) metadata_length); + if (ret != 0) { + goto out; + } + } + if (metadata_schema != NULL) { + ret = tsk_reference_sequence_set_metadata_schema(self->reference_sequence, + metadata_schema, (tsk_size_t) metadata_schema_length); + if (ret != 0) { + goto out; + } + } + if (url != NULL) { + ret = tsk_reference_sequence_set_url( + self->reference_sequence, url, (tsk_size_t) url_length); + if (ret != 0) { + goto out; + } + } + +out: + + return ret; +} + static int TSK_WARN_UNUSED tsk_table_collection_loadf_inited(tsk_table_collection_t *self, FILE *file) { @@ -10354,6 +10570,10 @@ tsk_table_collection_loadf_inited(tsk_table_collection_t *self, FILE *file) if (ret != 0) { goto out; } + ret = tsk_table_collection_load_reference_sequence(self, &store); + if (ret != 0) { + goto out; + } ret = kastore_close(&store); if (ret != 0) { goto out; @@ -10454,6 +10674,23 @@ tsk_table_collection_write_format_data(const tsk_table_collection_t *self, return ret; } +static int TSK_WARN_UNUSED +tsk_table_collection_reference_sequence_dump(const tsk_table_collection_t *self, + kastore_t *store, tsk_flags_t TSK_UNUSED(options)) +{ + const tsk_reference_sequence_t *ref = self->reference_sequence; + write_table_col_t write_cols[] = { + { "reference_sequence/data", (void *) ref->data, ref->data_length, KAS_UINT8 }, + { "reference_sequence/url", (void *) ref->url, ref->url_length, KAS_UINT8 }, + { "reference_sequence/metadata", (void *) ref->metadata, ref->metadata_length, + KAS_UINT8 }, + { "reference_sequence/metadata_schema", (void *) ref->metadata_schema, + ref->metadata_schema_length, KAS_UINT8 }, + { .name = NULL }, + }; + return write_table_cols(store, write_cols, 0); +} + int TSK_WARN_UNUSED tsk_table_collection_dump( const tsk_table_collection_t *self, const char *filename, tsk_flags_t options) @@ -10542,6 +10779,12 @@ tsk_table_collection_dumpf( if (ret != 0) { goto out; } + if (self->reference_sequence != NULL) { + ret = tsk_table_collection_reference_sequence_dump(self, &store, options); + if (ret != 0) { + goto out; + } + } ret = kastore_close(&store); if (ret != 0) { diff --git a/c/tskit/tables.h b/c/tskit/tables.h index 7235ef71cd..79ba0b0cff 100644 --- a/c/tskit/tables.h +++ b/c/tskit/tables.h @@ -538,6 +538,17 @@ typedef struct { tsk_size_t *record_offset; } tsk_provenance_table_t; +typedef struct { + char *data; + tsk_size_t data_length; + char *url; + tsk_size_t url_length; + char *metadata; + tsk_size_t metadata_length; + char *metadata_schema; + tsk_size_t metadata_schema_length; +} tsk_reference_sequence_t; + /** @brief A collection of tables defining the data for a tree sequence. */ @@ -554,6 +565,7 @@ typedef struct { /** @brief The metadata schema */ char *metadata_schema; tsk_size_t metadata_schema_length; + tsk_reference_sequence_t *reference_sequence; /** @brief The individual table */ tsk_individual_table_t individuals; /** @brief The node table */ @@ -4104,6 +4116,23 @@ int tsk_table_collection_compute_mutation_parents( int tsk_table_collection_compute_mutation_times( tsk_table_collection_t *self, double *random, tsk_flags_t TSK_UNUSED(options)); +int tsk_reference_sequence_init(tsk_reference_sequence_t *self); +int tsk_reference_sequence_free(tsk_reference_sequence_t *self); +bool tsk_reference_sequence_equals(const tsk_reference_sequence_t *self, + const tsk_reference_sequence_t *other, tsk_flags_t options); +int tsk_reference_sequence_copy(const tsk_reference_sequence_t *self, + tsk_reference_sequence_t **dest, tsk_flags_t options); +int tsk_reference_sequence_set_data(tsk_reference_sequence_t *self, + const char *reference_sequence, tsk_size_t reference_sequence_length); +int tsk_reference_sequence_set_url(tsk_reference_sequence_t *self, + const char *reference_sequence_url, tsk_size_t reference_sequence_url_length); +int tsk_reference_sequence_set_metadata(tsk_reference_sequence_t *self, + const char *reference_sequence_metadata, + tsk_size_t reference_sequence_metadata_length); +int tsk_reference_sequence_set_metadata_schema(tsk_reference_sequence_t *self, + const char *reference_sequence_metadata_schema, + tsk_size_t reference_sequence_metadata_schema_length); + /** @defgroup TABLE_SORTER_API_GROUP Low-level table sorter API. @{