Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for table metadata schema #339

Draft
wants to merge 10 commits into
base: main
Choose a base branch
from
4 changes: 4 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -58,3 +58,7 @@ name = "tree_traversals"

[[example]]
name = "forward_simulation"

[[example]]
name = "metadata_schema"
required-features = ["derive"]
29 changes: 29 additions & 0 deletions examples/metadata_schema.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
use tskit::prelude::*;
use tskit::TableCollection;

#[derive(serde::Serialize, serde::Deserialize, tskit::metadata::PopulationMetadata)]
#[serializer("serde_json")]
struct PopulationMetadata {
name: String,
}

fn main() {
let from_fp11 = r#"
{
"codec": "json",
"type": "object",
"name": "Population metadata",
"properties": {"name": {"type": "string"}}
}"#;

let mut tables = TableCollection::new(10.0).unwrap();
tables
.add_population_with_metadata(&PopulationMetadata {
name: "YRB".to_string(),
})
.unwrap();
tables
.set_json_metadata_schema_from_str(tskit::MetadataSchema::Populations, from_fp11)
.unwrap();
tables.dump("testit.trees", 0).unwrap();
}
7 changes: 7 additions & 0 deletions python_scripts/read_tablesfile.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import tskit
import sys

for f in sys.argv[1:]:
tables = tskit.TableCollection.load(f)
for pop in tables.populations:
print(pop)
1 change: 1 addition & 0 deletions python_scripts/requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
tskit = "0.5.1"
2 changes: 1 addition & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -435,7 +435,7 @@ pub use mutation_table::{MutationTable, MutationTableRow, OwnedMutationTable};
pub use node_table::{NodeTable, NodeTableRow, OwnedNodeTable};
pub use population_table::{OwnedPopulationTable, PopulationTable, PopulationTableRow};
pub use site_table::{OwnedSiteTable, SiteTable, SiteTableRow};
pub use table_collection::TableCollection;
pub use table_collection::{MetadataSchema, TableCollection};
pub use traits::IndividualLocation;
pub use traits::IndividualParents;
pub use traits::NodeListGenerator;
Expand Down
83 changes: 83 additions & 0 deletions src/table_collection.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,23 @@ use crate::TskReturnValue;
use crate::TskitTypeAccess;
use crate::{tsk_id_t, tsk_size_t};
use crate::{EdgeId, NodeId};
use libc::{c_char, strlen};
use ll_bindings::tsk_table_collection_free;
use mbox::MBox;

pub enum MetadataSchema {
Toplevel,
Edges,
Nodes,
Sites,
Mutations,
Individuals,
Populations,
Migrations,
#[cfg(feature = "provenance")]
Provenance,
}

/// A table collection.
///
/// This is a thin wrapper around the C type
Expand Down Expand Up @@ -1202,6 +1216,35 @@ impl TableCollection {
};
handle_tsk_return_value!(rv)
}

/// Set a metadata schema
///
/// # Examples
///
pub fn set_json_metadata_schema_from_str(
&mut self,
level: MetadataSchema,
schema: impl AsRef<str>,
) -> TskReturnValue {
println!("{} {}", schema.as_ref(), schema.as_ref().len());
let cstr = std::ffi::CString::new(schema.as_ref()).unwrap();
println!("{:?}", cstr);
let len = unsafe { strlen(cstr.as_bytes_with_nul().as_ptr() as *const c_char) };
println!("{:?}", cstr);
println!("{}", len);
let rv = match level {
MetadataSchema::Populations => unsafe {
ll_bindings::tsk_population_table_set_metadata_schema(
&mut (*self.inner).populations,
cstr.as_bytes_with_nul().as_ptr() as *const c_char,
len.try_into().unwrap(),
)
},
_ => unimplemented!("haven't done it yet"),
};
println!("rv = {}", rv);
handle_tsk_return_value!(rv)
}
}

impl TableAccess for TableCollection {
Expand Down Expand Up @@ -2296,3 +2339,43 @@ mod test_adding_migrations {
}
}
}

#[cfg(test)]
mod test_metadata_schema {
use super::*;

#[test]
fn population_metadata_schema() {
let json_schema3 = r#"{"codec":"json","type":"object","name":"Population metadata","properties:"{"name":{"type":"string"}}}"#;
let json_schema3 = r#"{"codec":"json","type":"object","name":"Population metadata","properties":{"name":{"type":"string"}}}"#;
let json_schema2 = r#"{"codec":"json","name":"Population metadata","properties":{"name":{"type":"string"}},"type":"object"}"#;
let json_schema = r#"{"codec":"json","name":"Population metadata","properties":{"name":{"type":"string"}},"type":"object"}"#;

// YOU CANNOT HAVE A TRAILING COMMA AT THE END!!!!!!
let from_fp11 = r#"
{
"codec": "json",
"type": "object",
"name": "Population metadata",
"properties": {"name": {"type": "string"}}
}"#;

assert_eq!(json_schema, json_schema2);
let mut tables = TableCollection::new(10.).unwrap();
assert!(tables
.set_json_metadata_schema_from_str(MetadataSchema::Populations, from_fp11)
.is_ok());
assert!(!unsafe { (*tables.as_ptr()).populations.metadata_schema.is_null() });
let len = unsafe { (*tables.as_ptr()).populations.metadata_schema_length };
assert!(len > 0, "{}", len);
let schema =
unsafe { std::ffi::CStr::from_ptr((*tables.as_ptr()).populations.metadata_schema) };
assert_eq!(schema.to_str().unwrap(), from_fp11);
tables.dump("foo.trees", 0).unwrap();

//let tables = TableCollection::new_from_file("bananas.tables").unwrap();
//let schema =
// unsafe { std::ffi::CStr::from_ptr((*tables.as_ptr()).populations.metadata_schema) };
//println!("from tskit = {}", schema.to_str().unwrap());
}
}