Skip to content

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), and edge_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
  • A single vertex ID (string).
  • An iterable of vertex IDs (e.g., list, tuple, set).
  • None is allowed and will return an empty set.
required

Returns:

Type Description
set[str]

A set of vertex identifiers. If vertices is None, returns an empty set. If a single vertex is provided, returns a one-element set.

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), and edge_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
  • A single vertex ID (string).
  • An iterable of vertex IDs (e.g., list, tuple, set).
  • None is allowed and will return an empty set.
required

Returns:

Type Description
set[str]

A set of vertex identifiers. If vertices is None, returns an empty set. If a single vertex is provided, returns a one-element set.

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.