GFA: derive block group name from filename on import - #93
Conversation
|
Something to consider is a whole genome and multiple chromosomes in a GFA. I think this is how to do GFA imports: Create a graph of the nodes/segments. Identify subgraphs and that is a blockgroup. If there exists a ref tag, use it, if not use the longest path name if they exist as the name. If neither exists, but there is only a single graph, give it a name based on the file. IF none of those conditions are met and there are multiple blockgroups, throw them all under the filename in a blockgroup with multiple graphs. Ensure to link the graphs into start/end nodes. |
|
For all the tests that call import_gfa, it'd be good to provide a string like "test graph" or "test sequence graph" instead of the empty string for the graph name |
…inding updates
GFA import now derives block group names from content rather than using a
blank default: SN:Z: ref tags → longest path/walk → filename stem. Multiple
disjoint subgraphs with distinct SN values each get their own block group.
Node IDs are now deterministically hashed (collection + segment + sequence),
so importing the same file twice raises NoChanges instead of stacking graphs.
CLI prints a summary line ("Imported N sequence graph(s): name1, name2").
Python binding import_gfa returns Vec<PyBlockGroup> (list of BlockGroup).
R binding import_gfa returns List of GenBlockGroup objects.
Four new GFA fixtures cover the naming cases: ref_tag_single, ref_tag_multi,
paths_no_ref, disjoint_graphs. Existing round-trip tests updated for new names.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
| let sn_tags = read_sn_tags(gfa_path); | ||
| bar.finish(); | ||
|
|
||
| // Determine block group name per segment: SN:Z: tags > longest path/walk > filename stem |
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
| .sequence(input_sequence) | ||
| .save(conn)?; | ||
| sequences_by_segment_id.insert(&segment.id, sequence.clone()); | ||
| // TODO: Node hash is always new, it's sorted by insert time via being a v7 uuid but maybe want to |
There was a problem hiding this comment.
This was making it so that importing the same GFA twice stacks the graphs on top of each other so you get for a graph A-B
start - A - B - end
\ /
A' - B'
| op.map(|op| (op, block_groups)) | ||
| } | ||
|
|
||
| fn read_sn_tags(gfa_path: &FilePath) -> HashMap<String, String> { |
There was a problem hiding this comment.
Should we have first parsed the whole file instead of extracting like this?
On rereading there's an issue with my implementation: connected segments with different SN tags are split between bgs, and disconnected subgraphs with the same name have the opposite issue. Working on a fix. |
Each connected component in the GFA link graph becomes its own block group. Names are still derived from SN:Z: tags (majority vote per component), longest path/walk, or filename stem — with _N suffixes to disambiguate when multiple components share a base name. Removes Kosaraju SCC from cycle-breaking: now checks for missing PATH_START/PATH_END edges directly, since each block group is guaranteed to be one connected component after this change. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…groups Re-imported diff GFAs now produce one block group per connected component. Collect sequences across all block groups instead of popping one. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
| track_database(conn, op_conn).unwrap(); | ||
| let _ = import_gfa(&context, &gfa_path, &collection_name, Sample::DEFAULT_NAME); | ||
|
|
||
| let block_groups = BlockGroup::query( |
There was a problem hiding this comment.
todo: replace sql query with proper method call
GFA imports always created block groups with an empty name, making them indistinguishable when importing multiple files and preventing correct deduplication checks.
block_group_nameparam to coreimport_gfa--graph-nameflag; defaults to file stemgraph_namekwarg; defaults to file stem