Disk Storage (.annnet)
The .annnet format is a lossless on-disk representation built on Zarr +
Parquet + JSON. This page documents the primary read/write API.
AnnNet Format
annnet.io.io_annnet.write(graph, path, *, compression='zstd', overwrite=False)
annnet.io.io_annnet.read(path, *, lazy=False)
Load graph from disk with zero loss.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
path
|
str | Path
|
Path to .annnet directory |
required |
lazy
|
bool
|
If True, delay loading large arrays until accessed |
False
|
Returns:
| Type | Description |
|---|---|
AnnNet
|
Reconstructed graph with all topology and metadata |
Internal helpers
Attributes
ANNNET_EXT = 'graph.annnet'
module-attribute
Classes
AnnNet
Sparse incidence-matrix graph with slices, attributes, parallel edges, and hyperedges.
The graph is backed by a DOK (Dictionary Of Keys) sparse matrix and exposes sliceed views and attribute tables stored as Polars DF (DataFrame). Supports: vertices, binary edges (directed/undirected), edge-entities (vertex-edge hybrids), k-ary hyperedges (directed/undirected), per-slice membership and weights, and Polars-backed attribute upserts.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
directed
|
bool
|
Whether edges are directed by default. Individual edges can override this. |
None
|
Notes
- Incidence columns encode orientation: +w on source/head, −w on target/tail for directed edges; +w on all members for undirected edges/hyperedges.
- Attributes are pure: structural keys are filtered out so attribute tables contain only user data.
See Also
add_vertex, add_edge, add_hyperedge, edges_view, vertices_view, slices_view
Functions
__init__(directed=None, n=0, e=0, annotations=None, annotations_backend='polars', **kwargs)
Initialize an empty incidence-matrix graph.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
directed
|
bool
|
Global default for edge directionality. Individual edges can override this. |
None
|
Notes
- Stores entities (vertices and edge-entities), edges (including parallels), and an incidence matrix in DOK (Dictionary Of Keys) sparse format.
- Attribute tables are Polars DF (DataFrame) with canonical key columns:
vertex_attributes(vertex_id),edge_attributes(edge_id),slice_attributes(slice_id), andedge_slice_attributes(slice_id, edge_id, weight). - A
'default'slice is created and set active.
_register_edge_as_entity(edge_id)
Make an existing edge connectable as an endpoint.
_propagate_to_shared_slices(edge_id, source, target)
INTERNAL: Add an edge to all slices that already contain both endpoints.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
edge_id
|
str
|
|
required |
source
|
str
|
|
required |
target
|
str
|
|
required |
_propagate_to_all_slices(edge_id, source, target)
INTERNAL: Add an edge to any slice containing either endpoint and insert the missing endpoint into that slice.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
edge_id
|
str
|
|
required |
source
|
str
|
|
required |
target
|
str
|
|
required |
_normalize_vertices_arg(vertices)
Normalize a single vertex or an iterable of vertices into a set.
This internal utility function standardizes input for methods like
in_edges() and out_edges() by converting the argument into a set
of vertex identifiers.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
vertices
|
str | Iterable[str] | None
|
|
required |
Returns:
| Type | Description |
|---|---|
set[str]
|
A set of vertex identifiers. If |
Notes
- Strings are treated as single vertex IDs, not iterables.
- If the argument is neither iterable nor a string, it is wrapped in a set.
- Used internally by API methods that accept flexible vertex arguments.
_is_directed_edge(edge_id)
Check if an edge is directed (per-edge flag overrides graph default).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
edge_id
|
str
|
|
required |
Returns:
| Type | Description |
|---|---|
bool
|
|
_resolve_snapshot(ref)
Resolve snapshot reference (label, dict, or AnnNet).
_current_snapshot()
Create snapshot of current state (uses AnnNet attributes).
Functions
_read_archive(infile, tmpdir)
_write_archive(src_dir, outfile)
_write_cache(*args, **kwargs)
_have_polars()
_df_from_dict(data)
Create a DataFrame from dict-of-columns using: - polars if available - else pandas
_write_parquet_df(df, path, *, compression='zstd')
Write a dataframe-like object to parquet: - polars DataFrame: df.write_parquet - pandas DataFrame: df.to_parquet(engine="pyarrow") - anything else: try narwhals -> pandas
_read_parquet(path)
Read parquet into: - polars DataFrame if available - else pandas DataFrame
_iter_rows(df)
Return rows as list[dict] for both: - polars DataFrame: .to_dicts() - pandas DataFrame: .to_dict(orient="records")
_write_dir(graph, path, *, compression='zstd', overwrite=False)
Write graph to disk with zero topology loss.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
path
|
str | Path
|
Target directory (e.g., "my_graph.annnet") |
required |
compression
|
str
|
Compression codec for Zarr/Parquet |
"zstd"
|
overwrite
|
bool
|
Allow overwriting existing directory |
False
|
Notes
Creates a self-contained directory with: - Zarr arrays for sparse matrices - Parquet tables for attributes/metadata - JSON for unstructured data
write(graph, path, *, compression='zstd', overwrite=False)
_write_structure(graph, path, compression)
Write sparse incidence matrix + all index mappings.
_write_tables(graph, path, compression)
_write_multilayers(graph, path, compression)
Write Kivela multilayer structures to disk.
_write_slices(graph, path, compression)
Write slice registry and memberships.
_write_audit(graph, path, compression)
Write history, snapshots, provenance.
_write_uns(graph, path)
Write unstructured metadata and results.
read(path, *, lazy=False)
Load graph from disk with zero loss.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
path
|
str | Path
|
Path to .annnet directory |
required |
lazy
|
bool
|
If True, delay loading large arrays until accessed |
False
|
Returns:
| Type | Description |
|---|---|
AnnNet
|
Reconstructed graph with all topology and metadata |
_load_structure(graph, path, lazy)
Load sparse matrix and index mappings.
_load_tables(graph, path)
Load Polars DataFrames.
_load_multilayers(graph, path)
Load Kivela multilayer structures.
_load_slices(graph, path)
Reconstruct slice registry and memberships.
_load_audit(graph, path)
Load history and provenance.
_load_uns(graph, path)
Load unstructured metadata.
Parquet GraphDir (Lossless)
annnet.io.Parquet_io.to_parquet(graph, path)
Write lossless GraphDir: vertices.parquet, edges.parquet, slices.parquet, edge_slices.parquet, manifest.json Wide tables (attrs as columns). Hyperedges stored with 'kind' and head/tail/members lists.
annnet.io.Parquet_io.from_parquet(path)
Read GraphDir (lossless) using bulk ops for speed.
Internal helpers
Classes
AnnNet
Sparse incidence-matrix graph with slices, attributes, parallel edges, and hyperedges.
The graph is backed by a DOK (Dictionary Of Keys) sparse matrix and exposes sliceed views and attribute tables stored as Polars DF (DataFrame). Supports: vertices, binary edges (directed/undirected), edge-entities (vertex-edge hybrids), k-ary hyperedges (directed/undirected), per-slice membership and weights, and Polars-backed attribute upserts.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
directed
|
bool
|
Whether edges are directed by default. Individual edges can override this. |
None
|
Notes
- Incidence columns encode orientation: +w on source/head, −w on target/tail for directed edges; +w on all members for undirected edges/hyperedges.
- Attributes are pure: structural keys are filtered out so attribute tables contain only user data.
See Also
add_vertex, add_edge, add_hyperedge, edges_view, vertices_view, slices_view
Functions
__init__(directed=None, n=0, e=0, annotations=None, annotations_backend='polars', **kwargs)
Initialize an empty incidence-matrix graph.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
directed
|
bool
|
Global default for edge directionality. Individual edges can override this. |
None
|
Notes
- Stores entities (vertices and edge-entities), edges (including parallels), and an incidence matrix in DOK (Dictionary Of Keys) sparse format.
- Attribute tables are Polars DF (DataFrame) with canonical key columns:
vertex_attributes(vertex_id),edge_attributes(edge_id),slice_attributes(slice_id), andedge_slice_attributes(slice_id, edge_id, weight). - A
'default'slice is created and set active.
_register_edge_as_entity(edge_id)
Make an existing edge connectable as an endpoint.
_propagate_to_shared_slices(edge_id, source, target)
INTERNAL: Add an edge to all slices that already contain both endpoints.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
edge_id
|
str
|
|
required |
source
|
str
|
|
required |
target
|
str
|
|
required |
_propagate_to_all_slices(edge_id, source, target)
INTERNAL: Add an edge to any slice containing either endpoint and insert the missing endpoint into that slice.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
edge_id
|
str
|
|
required |
source
|
str
|
|
required |
target
|
str
|
|
required |
_normalize_vertices_arg(vertices)
Normalize a single vertex or an iterable of vertices into a set.
This internal utility function standardizes input for methods like
in_edges() and out_edges() by converting the argument into a set
of vertex identifiers.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
vertices
|
str | Iterable[str] | None
|
|
required |
Returns:
| Type | Description |
|---|---|
set[str]
|
A set of vertex identifiers. If |
Notes
- Strings are treated as single vertex IDs, not iterables.
- If the argument is neither iterable nor a string, it is wrapped in a set.
- Used internally by API methods that accept flexible vertex arguments.
_is_directed_edge(edge_id)
Check if an edge is directed (per-edge flag overrides graph default).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
edge_id
|
str
|
|
required |
Returns:
| Type | Description |
|---|---|
bool
|
|
_resolve_snapshot(ref)
Resolve snapshot reference (label, dict, or AnnNet).
_current_snapshot()
Create snapshot of current state (uses AnnNet attributes).
Functions
_deserialize_edge_layers(data)
Inverse of _serialize_edge_layers.
Returns eid -> aa or (aa, bb) (tuples).
_deserialize_layer_tuple_attrs(data)
Inverse of _serialize_layer_tuple_attrs.
_deserialize_node_layer_attrs(data)
Inverse of _serialize_node_layer_attrs.
_deserialize_VM(data)
Inverse of _serialize_VM.
_safe_df_to_rows(df)
Return list[dict] rows from polars/pandas/narwhals; return [] on None/empty/unknown.
_serialize_edge_layers(edge_layers)
Convert edge_layers[eid] (aa or (aa, bb)) into JSON-safe form.
- intra: aa -> {"kind": "single", "layers": [list(aa)]}
- inter/coupling: (aa, bb) -> {"kind": "pair", "layers": [list(aa), list(bb)]}
_serialize_layer_tuple_attrs(layer_attrs)
_layer_attrs: {aa_tuple -> {attr_name: value}} -> JSON-safe: [{"layer": list(aa), "attrs": {...}}, ...]
_serialize_node_layer_attrs(nl_attrs)
(u, aa) -> {attrs} -> [{"node": u, "layer": list(aa), "attrs": {...}}, ...]
_serialize_VM(VM)
Serialize V_M = {(u, aa)} to JSON-safe list of dicts.
_iter_rows(df)
Return rows as list[dict] for both: - polars DataFrame: .to_dicts() - pandas DataFrame: .to_dict(orient="records")
_read_parquet(path)
Read parquet into: - polars DataFrame if available - else pandas DataFrame
_write_parquet_df(df, path, *, compression='zstd')
Write a dataframe-like object to parquet: - polars DataFrame: df.write_parquet - pandas DataFrame: df.to_parquet(engine="pyarrow") - anything else: try narwhals -> pandas
_build_dataframe_from_rows(rows)
Build a DataFrame from a list of row records using available backends.
pd_build_dataframe_from_rows(rows)
Build a DataFrame from a list of row records using available backends.
_strip_nulls(d)
_is_directed_eid(graph, eid)
Get edge directedness. Default False for hyperedges, True for binary.
_coerce_coeff_mapping(val)
Normalize various serialized forms into {vertex: {__value: float}|float}. Accepts dict | list | list-of-dicts | list-of-pairs | JSON string.
_is_nullish(val)
_as_list_or_empty(val)
_endpoint_coeff_map(edge_attrs, private_key, endpoint_set)
Return {vertex: float_coeff} for the given endpoint_set. Reads from edge_attrs[private_key] which may be serialized in multiple shapes. Missing endpoints default to 1.0.
_build_attr_map(df, key_col)
Build {key: attrs} mapping from a dataframe-like table.
to_parquet(graph, path)
Write lossless GraphDir: vertices.parquet, edges.parquet, slices.parquet, edge_slices.parquet, manifest.json Wide tables (attrs as columns). Hyperedges stored with 'kind' and head/tail/members lists.
from_parquet(path)
Read GraphDir (lossless) using bulk ops for speed.