Skip to content

GFA: derive block group name from filename on import - #93

Open
bobvh wants to merge 4 commits into
mainfrom
gfa-import-syntax
Open

GFA: derive block group name from filename on import#93
bobvh wants to merge 4 commits into
mainfrom
gfa-import-syntax

Conversation

@bobvh

@bobvh bobvh commented Apr 14, 2026

Copy link
Copy Markdown
Member

GFA imports always created block groups with an empty name, making them indistinguishable when importing multiple files and preventing correct deduplication checks.

  • Add block_group_name param to core import_gfa
  • CLI: add --graph-name flag; defaults to file stem
  • Python: add optional graph_name kwarg; defaults to file stem
  • All internal/test callers pass "" to preserve existing behavior

@bobvh bobvh linked an issue Apr 14, 2026 that may be closed by this pull request
@Chris7

Chris7 commented Apr 14, 2026

Copy link
Copy Markdown
Member

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.

@dkhofer

dkhofer commented Apr 14, 2026

Copy link
Copy Markdown
Member

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>
@bobvh
bobvh force-pushed the gfa-import-syntax branch from 5ec416c to 8bda50f Compare June 5, 2026 14:27
Comment thread src/imports/gfa.rs Outdated
let sn_tags = read_sn_tags(gfa_path);
bar.finish();

// Determine block group name per segment: SN:Z: tags > longest path/walk > filename stem

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This addresses @Chris7 ' suggestion

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Comment thread src/imports/gfa.rs
.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

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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' 

Comment thread src/imports/gfa.rs
op.map(|op| (op, block_groups))
}

fn read_sn_tags(gfa_path: &FilePath) -> HashMap<String, String> {

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we have first parsed the whole file instead of extracting like this?

@bobvh

bobvh commented Jun 5, 2026

Copy link
Copy Markdown
Member Author

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.

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.

bobvh and others added 2 commits June 5, 2026 12:23
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>
Comment thread src/imports/gfa.rs
track_database(conn, op_conn).unwrap();
let _ = import_gfa(&context, &gfa_path, &collection_name, Sample::DEFAULT_NAME);

let block_groups = BlockGroup::query(

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

todo: replace sql query with proper method call

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

GFA import - block group naming

3 participants