Skip to content

Graph

AnnNet is the graph object. annnet.Graph is the same class.

An AnnNet object holds the structure (nodes, edges, hyperedges), the attribute tables, and the slices and layers. The members below are grouped by what they do:

  • Build and edit: add_nodes, add_edges, remove_nodes, remove_edges, make_undirected.
  • Nodes and edges: N, E, shape, has_node, has_edge, degree, neighbors, in_neighbors, out_neighbors, predecessors, successors, incident_edges, edge_list, entity_kinds.
  • Layers: at, exists, is_multilayer, nv_supra, supra_nodes, supra_shape.
  • Attributes and metadata: attrs, uns, summary, provenance.
  • Matrices: A, B, H, S, L, matrices, idx, cache.
  • Namespaces: slices, layers, ops, history, spaces, and the backend accessors nx, ig, gt.
  • Views and files: view, read, write.

The eight attribute tables are under attrs: nodes, edges, slices, aspects, layers, edge_slices, node_layers and elementary_layers. See Attributes and the annotations guide.

Matrices

All matrices are SciPy sparse arrays. Rows are nodes (placements, on a multilayer graph) and edge entities. The properties use the default options. anet.matrices.<name>(...) takes options, and gives the matrix together with the maps between IDs and positions (see Indexing).

property anet.matrices rows × columns edges in it values
anet.B binary() entities × edges binary edges +weight on the source, -weight on the target
anet.S signed(), incidence() entities × edges all edges the coefficients; the two entries of a self-loop cancel
anet.H hypergraph() entities × edges hyperedges 1 if the edge holds the entity, on any side
anet.A adjacency() entities × entities binary edges the edge weight, in the row of the source; a self-loop is on the diagonal
anet.L laplacian() entities × entities binary edges the degree matrix minus A; each row sums to zero

A hyperedge is not in A or L: give kinds= to adjacency() to choose how to include it. incidence(kinds=None, signed=True) gives the incidence for the edge kinds that you select, with or without the coefficients.

On a multilayer graph, anet.layers has the matrices over all placements: supra_adjacency(), its parts build_intra_block(), build_inter_block() and build_coupling_block(), supra_laplacian() and transition_matrix(). See Layers and the layers guide.

The graph model guide explains the matrices with an example.

Edge records

anet.E.at(edge_id) gives an EdgeView. Its fields:

  • kind: the structure, binary, hyper or node_edge;
  • directed: the direction, separate from the kind;
  • ml_kind: the place in a multilayer graph, intra, inter or coupling. For a graph without layers, it is intra.

The same fields have the same names in the anet.E[...] columns, in the derived edge table and in anet.summary().

AnnNet

annnet.core.graph.AnnNet

Incidence-based graph with slices, multilayer coordinates, and rich edge types.

AnnNet stores topology in a sparse incidence matrix backed by canonical entity and edge registries. A row represents an entity, typically a node or an edge-entity, and a column represents an edge. The class supports:

  • binary directed and undirected edges
  • hyperedges, including directed head/tail hyperedges
  • edge-entities that can themselves participate as endpoints
  • slice membership and per-slice edge weights
  • optional multilayer coordinates on nodes and edges
  • dataframe-backed attribute storage

Parameters:

Name Type Description Default
directed bool | None

Default directedness for newly created binary edges. If None, methods fall back to directed semantics unless a per-edge flag is set.

None
annotations dict | None

Pre-built annotation tables to use instead of creating empty tables.

None
annotations_backend ('auto', 'polars', 'pandas', 'pyarrow')

Preferred backend for newly initialized annotation tables. "auto" prefers the first installed supported backend.

"auto"
aspects dict[str, list[str]] | None

Initial multilayer aspect declaration. If omitted, the graph starts flat with a single placeholder aspect "_".

None
**kwargs Any

Initial graph-level attributes stored in :attr:graph_attributes.

{}
Notes

Directed incidence columns use positive values for sources or heads and negative values for targets or tails. Undirected binary edges and undirected hyperedges use positive values for all incident entities.

See Also

add_node add_edge add_nodes add_edges view

Attributes

N property
N

The node sequence.

Returns:

Type Description
NodeSequence

The nodes in graph order. Iterating it yields ids, a string key reads or writes one attribute column, an integer key gives the node at that position, and select and find filter it.

Examples:

>>> list(anet.N)
>>> anet.N['kind']
>>> anet.N['kind'] = values
>>> anet.N.find(id='A')
E property
E

The edge sequence.

Returns:

Type Description
EdgeSequence

The edges in graph order, with the same keys as :attr:N. The direction, the weight, and the kind of an edge read like a column, so a filter over them needs no attribute.

Examples:

>>> list(anet.E)
>>> anet.E['weight']
>>> anet.E.select(directed=True)
shape property
shape

Graph shape as (len(anet.N), len(anet.E)).

Returns:

Type Description
tuple[int, int]

Distinct node count and structural edge count, both maintained counters. Use :attr:supra_shape for the placement count.

is_multilayer property
is_multilayer

Whether the graph has declared multilayer aspects.

Returns:

Type Description
bool

True when the graph has user-declared aspects. Flat graphs use the internal sentinel aspect "_" and return False.

nv_supra property
nv_supra

Number of supra-nodes (rows of the supra-incidence matrix).

Returns:

Type Description
int

Count of entities whose internal kind is "node" — one per (node_id, layer_coord) pair. In a flat graph this equals :attr:nv; in a multilayer graph it equals the sum over nodes of the number of layers each node inhabits.

supra_shape property
supra_shape

Supra-matrix shape as (nv_supra, len(anet.E)).

Returns:

Type Description
tuple[int, int]

Supra-incidence row count and edge count.

attrs property
attrs

The eight attribute addresses, read and written one way.

Returns:

Type Description
Attrs

Reads return detached copies: anet.attrs.<address> is the stored table, row(address, key) one row as a dict and rows(address) many. table(address, derived=True, ...) is the derived frame and schema describes an address without building one. Writes are named: update merges fields, replace swaps a whole table and delete removes attributes. select is a live query over rows, and from_frame turns the rows of a table you filtered into a fixed selection.

Examples:

>>> anet.attrs.update('nodes', {'A': {'symbol': 'TP53'}})
>>> anet.attrs.row('nodes', 'A').get('symbol')
>>> anet.attrs.update('edge_slices', {('baseline', 'e1'): {'weight': 0.5}})
>>> anet.attrs.select('edges', confidence__gte=0.8).keys
>>> table = anet.attrs.table('nodes')  # filter it with your dataframe library
>>> anet.attrs.from_frame('nodes', table[table['score'] > 0.5]).keys
uns property
uns

Graph-level unstructured metadata.

Returns:

Type Description
dict

Mutable dictionary of graph-level attributes.

provenance property
provenance

What this graph was built from (anet.provenance).

Callable, so anet.provenance() is the table of sources and anet.provenance.record(...) is how a reader adds to it. The records live in uns, so they survive whatever the graph survives.

Returns:

Type Description
Provenance

Examples:

>>> anet.provenance.record('OmniPath', version='2024.1')
>>> anet.provenance()
A property
A

Return the adjacency matrix.

Returns:

Type Description
sparray

A self-loop lands on the diagonal. A boundary edge joins nothing and a hyperedge names more than two entities, so neither is here.

B property
B

Return the incidence matrix of the binary edges.

Returns:

Type Description
sparray

Rows are entities and columns are binary edges, both in the order the store holds them.

H property
H

Return the incidence matrix of the hyperedges.

Returns:

Type Description
sparray

Unsigned, so an entry reports that a hyperedge holds an entity rather than which side it holds it on.

S property
S

Return the coefficient incidence matrix of every edge.

Returns:

Type Description
sparray

Signed, so the two entries of a self-loop cancel and a stoichiometric column carries the coefficients the user set.

L property
L

Return the graph Laplacian, the degree matrix minus the adjacency.

Returns:

Type Description
sparray

Every row sums to zero.

matrices property
matrices

Return the parameterized-matrix namespace of this graph.

Returns:

Type Description
MatrixNamespace
idx property
idx

Index lookup namespace.

Returns:

Type Description
IndexManager

Manager for entity-to-row and edge-to-column index lookups.

cache property
cache

Sparse matrix cache namespace.

Returns:

Type Description
CacheManager

Manager for derived sparse matrix formats such as CSR and CSC.

slices property
slices

Slice operations namespace.

Returns:

Type Description
SliceManager

Manager exposing slice creation, membership, set operations, and slice-level analysis.

Examples:

>>> anet.slices.add('baseline')
>>> anet.slices.active = 'baseline'
>>> anet.slices.list()
layers property
layers

Layer operations namespace.

Returns:

Type Description
LayerAccessor

Manager for multilayer aspects, layer coordinates, supra matrices, and layer set operations.

Notes

All multilayer configuration and layer-aware analysis lives here.

Examples:

>>> anet.layers.set_aspects(['condition'], {'condition': ['ctrl', 'stim']})
>>> anet.layers.list_layers()
>>> anet.attrs.table('layers', derived=True)
ops property
ops

Structural operations namespace.

Returns:

Type Description
OperationsAccessor

Manager for subgraphs, copies, reversals, incidence extraction, and memory inspection.

Examples:

>>> H = anet.ops.subgraph(['A', 'B', 'C'])
>>> M = anet.ops.node_incidence_matrix(sparse=True)
>>> usage = anet.ops.memory_usage()
history property
history

Mutation history and snapshot namespace.

Returns:

Type Description
HistoryAccessor

Callable namespace: anet.history() reads the log, and its methods enable it, clear it, export it, mark it, and snapshot the graph.

Examples:

>>> anet.history()
>>> anet.history.snapshot('before')
spaces property
spaces

Node membership in named external-axis bindings (see :class:annnet.Space).

nx property
nx

NetworkX interoperability namespace.

Returns:

Type Description
_NXBackendAccessor

Lazy proxy that converts to NetworkX only when an algorithm or backend graph is requested.

Examples:

>>> anet.nx.backend()
>>> anet.nx.shortest_path(anet, 'A', 'B')
ig property
ig

Igraph interoperability namespace.

Returns:

Type Description
_IGBackendAccessor

Lazy proxy that converts to igraph only when requested.

gt property
gt

graph-tool interoperability namespace.

Returns:

Type Description
_GTBackendAccessor

Lazy proxy that converts to graph-tool only when requested.

Functions

add_nodes
add_nodes(nodes, slice=None, layer=None, **attributes)

Add one node or many nodes.

This is the canonical public entry point for node creation. Use it for both single-node and batch insertion.

Parameters:

Name Type Description Default
nodes str | dict | tuple | Iterable

Node specification or iterable of specifications.

Accepted single-node forms are:

  • "A"
  • {"node_id": "A", "kind": "source"}
  • {"id": "A", ...}
  • {"name": "A", ...}
  • ("A", {"kind": "source"})

Accepted batch forms are iterables of the same specifications.

required
slice str

Slice receiving the inserted nodes. If omitted, the active slice is used.

None
layer str | tuple | dict

Layer coordinate for inserted nodes in multilayer graphs. A string is valid only for single-aspect graphs; a tuple must already be in aspect order; a dict maps aspect name to layer value.

None
**attributes Any

Attributes applied to a single node. These are merged with attributes in nodes when nodes is a single node.

{}

Returns:

Type Description
str | list[str]

The inserted node ID for a single node, or a list of node IDs for batch insertion.

Raises:

Type Description
ValueError

If a dictionary node specification does not contain "node_id", "id", or "name".

Notes

Node attributes are stored in :attr:obs and can be edited through :attr:attrs. In multilayer graphs, omitting layer places the node on the placeholder layer coordinate.

Examples:

>>> anet = AnnNet()
>>> anet.add_nodes('A', kind='source')
'A'
>>> anet.add_nodes(
...     [
...         {'node_id': 'B', 'kind': 'relay'},
...         ('C', {'kind': 'sink'}),
...     ]
... )
['B', 'C']
add_edges
add_edges(*args, **kwargs)

Add one edge, many edges, or hyperedges.

This is the canonical public entry point for all edge creation. It handles binary edges, directed and undirected edges, edge-entities, and hyperedges through the shape of the input specification.

Parameters:

Name Type Description Default
*args Any

Edge specification. Common forms are:

  • anet.add_edges("A", "B")
  • anet.add_edges("A", "B", weight=2.0, edge_id="e1")
  • anet.add_edges({"source": "A", "target": "B"})
  • anet.add_edges([{"source": "A", "target": "B"}, ...])
  • anet.add_edges([{"members": ["A", "B", "C"]}, ...])
  • anet.add_edges([{"tail": ["A"], "head": ["B", "C"]}, ...])
  • anet.add_edges([{"edge_id": "EE1", ...}, ...], as_entity=True)
()
**kwargs Any

Options for single-edge or batch insertion.

{}

Other Parameters:

Name Type Description
source str

Source endpoint for a binary edge.

src str

Source endpoint for a binary edge.

target str

Target endpoint for a binary edge.

tgt str

Target endpoint for a binary edge.

weight float

Incidence weight for the edge.

edge_id str

Explicit edge identifier. If omitted, an edge_N ID is assigned.

directed bool

Directedness for a single edge.

edge_directed bool

Directedness for edge specs in batch input.

slice str

Slice receiving the inserted edges. If omitted, the active slice is used.

as_entity bool

If True, each created edge is also registered as an entity so it can be used as the endpoint of later edges. In batch mode, items that carry no source/target are treated as null-endpoint edge-entity placeholders and require this flag to be set.

parallel ('update', 'error', 'parallel')

Policy for single-edge insertion when edge_id is not supplied and the same endpoints already have an edge. "update" reuses the existing edge; "parallel" creates an additional edge; "error" raises ValueError. Ignored in batch mode.

propagate ('none', 'shared', 'all')

Slice propagation policy. "shared" adds the edge to every slice containing both endpoints; "all" adds it to every slice containing either endpoint.

flexible dict

Data-driven direction policy. Requires keys "var" and "threshold". Single-edge path only.

default_weight float

Batch default for edge specs without an explicit weight.

default_edge_directed bool

Batch default directedness.

default_propagate ('none', 'shared', 'all')

Batch default propagation policy.

default_edge_type str

Batch default edge type stored in the edge record.

default_slice_weight float

Batch per-slice weight override.

Returns:

Type Description
str | list[str]

Edge ID for single-edge insertion, or a list of edge IDs for batch insertion.

Raises:

Type Description
TypeError

If unsupported keyword arguments are supplied for batch insertion.

ValueError

If the edge specification is structurally invalid.

Notes

Hyperedges are detected from dictionaries containing "members" for undirected hyperedges or "head"/"tail" for directed hyperedges. Binary edges use "source"/"target" or "src"/"tgt".

For a full guide covering all input forms, dispatch logic, parallel policy, propagation, flexible direction, and batch formats, see the Adding edges reference page.

Examples:

>>> anet = AnnNet(directed=True)
>>> anet.add_nodes(['A', 'B', 'C'])
['A', 'B', 'C']
>>> anet.add_edges('A', 'B', edge_id='e1', weight=0.5)
'e1'
>>> anet.add_edges(
...     [
...         {'source': 'B', 'target': 'C'},
...         {'members': ['A', 'B', 'C'], 'edge_id': 'h1'},
...     ]
... )
['edge_0', 'h1']
remove_nodes
remove_nodes(node_ids, *, errors='raise')

Remove one node or many nodes.

Parameters:

Name Type Description Default
node_ids str | tuple | Iterable[str | tuple]

Node ID, explicit multilayer node key, or iterable of IDs/keys.

required
errors ('raise', 'ignore')

"raise" (NetworkX convention) raises KeyError listing the unknown IDs. "ignore" silently skips them.

"raise"

Returns:

Type Description
None
Notes

Incident edges are removed with each node.

Examples:

>>> anet.remove_nodes('A')
>>> anet.remove_nodes(['B', 'C'])
>>> anet.remove_nodes('nope', errors='ignore')
remove_edges
remove_edges(edge_ids, *, errors='raise')

Remove one edge or many edges.

Parameters:

Name Type Description Default
edge_ids str | Iterable[str]

Edge ID or iterable of edge IDs to remove.

required
errors ('raise', 'ignore')

"raise" (NetworkX convention) raises KeyError listing the unknown IDs. "ignore" silently skips them.

"raise"

Returns:

Type Description
None

Examples:

>>> anet.remove_edges('e1')
>>> anet.remove_edges(['e2', 'e3'])
>>> anet.remove_edges('nope', errors='ignore')
make_undirected
make_undirected(*, drop_flexible=True, update_default=True)

Convert all existing edges to undirected form in place.

Parameters:

Name Type Description Default
drop_flexible bool

If True, clear flexible-direction policies after rewriting edge incidence signs.

True
update_default bool

If True, set anet.directed = False so future edges are undirected unless explicitly overridden.

True

Returns:

Type Description
AnnNet

The modified graph, returned for chaining.

Notes

Directed binary edges are rewritten from signed incidence (+w, -w) to unsigned incidence (+w, +w). Directed hyperedges are converted to undirected hyperedges over the union of their head and tail members.

Examples:

>>> anet = AnnNet(directed=True)
>>> anet.add_nodes(['A', 'B'])
['A', 'B']
>>> anet.add_edges('A', 'B')
'edge_0'
>>> anet.make_undirected()
AnnNet(...)
has_node
has_node(node_id)

Check whether a node exists.

Parameters:

Name Type Description Default
node_id str | tuple

Bare node ID, or explicit (node_id, layer_coord) tuple for multilayer graphs.

required

Returns:

Type Description
bool

True if the graph contains a node entity matching node_id.

Notes

In multilayer graphs, a bare node ID returns True if that node is present on at least one layer coordinate.

has_edge
has_edge(source=None, target=None, edge_id=None)

Check whether an edge exists.

Parameters:

Name Type Description Default
source str

Source endpoint.

None
target str

Target endpoint.

None
edge_id str

Edge identifier.

None

Returns:

Type Description
bool | tuple[bool, list[str]]

If only edge_id is provided, returns a boolean. If source and target are provided, returns (exists, edge_ids). If all three arguments are provided, returns whether that exact edge ID connects the given endpoints.

Raises:

Type Description
ValueError

If the argument combination is invalid.

Examples:

>>> anet.has_edge(edge_id='e1')
True
>>> anet.has_edge('A', 'B')
(True, ['e1'])
degree
degree(entity_id)

Return the number of structural edges touching one entity.

Parameters:

Name Type Description Default
entity_id str | tuple

Node ID, edge-entity ID, or explicit multilayer entity key.

required

Returns:

Type Description
int

The number of distinct incident structural edges, read off the incident-edge index the store maintains, so the cost is the degree and never the size of the graph and no matrix is built. A self-loop and a hyperedge each count once; an edge of weight zero still counts; a placeholder edge never does. A missing entity has degree 0.

neighbors
neighbors(entity_id)

Return adjacent entities for a node or an edge-entity.

Parameters:

Name Type Description Default
entity_id str

Entity identifier.

required

Returns:

Type Description
list[str]

Neighbor identifiers reachable through incident edges.

in_neighbors
in_neighbors(node_id)

Return inward neighbors of a node.

Parameters:

Name Type Description Default
node_id str

Node identifier.

required

Returns:

Type Description
list[str]

Neighbor identifiers reachable via incoming or undirected edges.

out_neighbors
out_neighbors(node_id)

Return outward neighbors of a node.

Parameters:

Name Type Description Default
node_id str

Node identifier.

required

Returns:

Type Description
list[str]

Neighbor identifiers reachable via outgoing or undirected edges.

predecessors
predecessors(node_id)

Alias for :meth:in_neighbors.

Parameters:

Name Type Description Default
node_id str

Node identifier.

required

Returns:

Type Description
list[str]

Predecessor identifiers.

successors
successors(node_id)

Alias for :meth:out_neighbors.

Parameters:

Name Type Description Default
node_id str

Node identifier.

required

Returns:

Type Description
list[str]

Successor identifiers.

incident_edges
incident_edges(nodes, direction='both')

Return edges incident to one or more nodes.

Parameters:

Name Type Description Default
nodes str | Iterable[str]

One node identifier or an iterable of identifiers.

required
direction ('in', 'out', 'both')

Directional filter applied to binary edges. Undirected edges are included for both "in" and "out".

"in"

Returns:

Type Description
list[tuple[int, EdgeView]]

Pairs of (column_index, edge_view) as returned by :meth:get_edge, materialized for consistency with the sibling nodes / edges / edge_list APIs which all return lists.

Raises:

Type Description
ValueError

If direction is not "in", "out", or "both".

Examples:

>>> anet.incident_edges('A', direction='out')
[(0, EdgeView(edge_id='e0', kind='binary', ...))]
edge_list
edge_list()

Materialize binary edges as endpoint tuples.

Returns:

Type Description
list[tuple[str, str, str, float]]

Tuples of (source, target, edge_id, weight) for binary and node-edge records. Hyperedges and endpoint-less placeholders are omitted. The weight reflects the active slice's per-edge override when one is set; otherwise the edge's stored weight.

entity_kinds
entity_kinds()

Return the kind of every entity — 'node' or 'edge' — by its id.

An entity is a node, or an edge that is a node in its own right. The mapping is built on each call, so changing it changes nothing.

global_count
global_count(kind)

Count unique members present across slices.

Parameters:

Name Type Description Default
kind ('nodes', 'edges', 'entities')

Membership domain. "nodes" counts slice node members, "edges" counts slice edge members, and "entities" counts the union of both domains.

"nodes"

Returns:

Type Description
int

Number of unique members observed in slice membership.

Raises:

Type Description
ValueError

If kind is not one of "nodes", "edges", or "entities".

Notes

This is a slice-membership count, not a storage count. For graph storage counts, use :meth:ncount and :meth:ecount.

at
at(node_id, **aspects)

Return the node-layer key one node sits on, naming its aspects.

The key is what every layered call takes — add_edges, layers.node_attrs, slices.add_nodes. Writing it by hand means writing a tuple in the graph's aspect order, which is a fact about the graph that a call site should not have to hold.

Parameters:

Name Type Description Default
node_id str

The node.

required
**aspects

One value per declared aspect, by name.

{}

Returns:

Type Description
tuple

(node_id, layer_coord).

Raises:

Type Description
KeyError

If an aspect is unknown or unnamed, or if the node is not on that node-layer. Use :meth:exists to ask without raising.

Examples:

>>> anet.at('akt', condition='stim')
('akt', ('stim',))
exists
exists(node_id, **aspects)

Whether one node sits on the node-layer its aspects name.

Parameters:

Name Type Description Default
node_id str

The node.

required
**aspects

One value per declared aspect, by name.

{}

Returns:

Type Description
bool

Raises:

Type Description
KeyError

If an aspect is unknown or unnamed. A missing node is False; a malformed question still raises.

Examples:

>>> anet.exists('akt', condition='stim')
True
supra_nodes
supra_nodes()

Return all (node_id, layer_coord) supra-nodes.

Returns:

Type Description
list[tuple[str, tuple[str, ...]]]

One entry per row of the supra-incidence matrix. In flat graphs the layer coordinate is the sentinel ('_',).

See Also

nodes : unique node IDs (one per node regardless of layer).

summary
summary()

Return a structured summary of the graph, built without a frame or a matrix.

Returns:

Type Description
Summary

Counts, aspects, slices, the attribute fields at every address and the edge kind / direction tallies, with a bounded readable repr.

view
view(
    nodes=None,
    edges=None,
    layers=None,
    slices=None,
    *,
    predicate=None,
    boundary="closed"
)

Create a live, read-only, composable view of this graph.

Parameters:

Name Type Description Default
nodes id | (node_id, layer) | Iterable | NodeSequence | RowSelection | mask

Bare ids select every existing placement of those nodes within the other filters; explicit (node_id, layer) keys select those placements alone. A anet.N.select(...) selection is live; a anet.attrs.select('node_layers', ...) selection keeps its placements. Nothing here ever creates a placeholder placement.

None
edges id | Iterable | EdgeSequence | RowSelection

Edge ids or a anet.E.select(...) selection. Edge-slice rows must be projected explicitly with .project('edges').

None
layers coordinate | Iterable | LayerSelection | RowSelection

One layer coordinate, a collection of them, anet.layers.where(...) or anet.attrs.select('layers', ...).

None
slices id | Iterable | SliceMembership

One slice id or several (their union), or the membership a slice operation such as anet.slices.intersect([...]) gives back, taken as an explicit node/edge constraint.

None
predicate callable

A node-id predicate, the advanced escape hatch. Its exceptions propagate with the offending id.

None
boundary ('closed', 'open')

closed keeps an edge only when its complete endpoint set is selected. open keeps the edges touching the selected entities and expands to their full endpoints — one hop, not a neighbourhood.

"closed"

Returns:

Type Description
GraphView

Live against this graph, read-only, and narrowed further with V.view(...). V.materialize() builds an editable copy.

read classmethod
read(path, **kwargs)

Read a graph from the native .annnet format.

Parameters:

Name Type Description Default
path str | Path

Input file path.

required
**kwargs

Passed to annnet.io.annnet_format.read.

{}

Returns:

Type Description
AnnNet

Deserialized graph.

Examples:

>>> anet = AnnNet.read('graph.annnet')
write
write(path, *, matrix=False, **kwargs)

Write the graph to the native .annnet format.

Parameters:

Name Type Description Default
path str | Path

Output file path.

required
matrix bool

Also persist the incidence matrix. The records are the source of truth and fully reconstruct it — including explicit coefficients, which are written as records data either way — so this is a size/load-time trade, never a correctness one. Left off, read defers the rebuild until the matrix is first touched, which is usually cheaper than loading it. Turn it on for graphs large enough that the rebuild dominates.

False
**kwargs

Passed to annnet.io.annnet_format.write. Notably attached=, which says what to do with node-layer values held in an attached array: "materialise" (the default) writes them out, "drop" leaves them out deliberately, "error" refuses. None of the three loses them quietly.

{}

Returns:

Type Description
None

Examples:

>>> anet.write('graph.annnet')  # matrix rebuilt on demand
>>> anet.write('graph.annnet', matrix=True)  # cache it alongside

Endpoint

One side of one edge: the node, and the layer it sits in. as_endpoint gives a stored endpoint the same shape, whether or not the graph has layers. See the annotations guide.

annnet.core._records.Endpoint

One side of one edge: the node, and the layer it sits in.

The store spells an endpoint two ways — a bare id in a flat graph, an (id, layer) pair in a layered one — so reading one meant asking which it was::

node = next(iter(sides.source))
node_id = node[0] if isinstance(node, tuple) else node

That check is a defect rather than an idiom. A graph holding both layered and unlayered edges makes it wrong, and nothing reports it. An endpoint read through :func:as_endpoint has one shape everywhere, and layer is None when there is not one.

The positional shape is the store's, so endpoint[0] is the id and endpoint[1] is the layer. str(endpoint) is the id, which is what a label, a dataframe cell and a join all want.

Examples:

>>> as_endpoint(('akt', ('stim',)))
Endpoint(node_id='akt', layer=('stim',))
>>> str(as_endpoint('akt'))
'akt'

Attributes

key property
key

The endpoint as the store spells it: a bare id, or an (id, layer) pair.

annnet.core._records.as_endpoint

as_endpoint(value)

Return one stored endpoint as an :class:Endpoint.

Parameters:

Name Type Description Default
value str | tuple[str, tuple[str, ...]] | Endpoint

An endpoint in any shape the store holds.

required

Returns:

Type Description
Endpoint

annnet.core._records.as_endpoints

as_endpoints(side)

Return one side of an edge as a frozenset of :class:Endpoint.

Parameters:

Name Type Description Default
side Iterable

One side of an edge, as :func:annnet.core._structure.edge_sides holds it.

required

Returns:

Type Description
frozenset[Endpoint]

Provenance

The sources that a graph was built from. The readers of annnet add a record for each source they read: its name, format, location, version, the time and a checksum. Read the records with anet.provenance().

annnet.core._provenance.Provenance

What one graph was built from (anet.provenance).

Callable, so anet.provenance() is the table and anet.provenance.record(...) is how a reader adds to it. A reader reaching for the module directly would be reading a private part of the core from outside it, which is what this accessor exists to avoid.

Functions

__call__
__call__(*, backend=None)

Every source record, as a table.

record
record(name, *, uri=None, checksum=True, **fields)

Record one source this graph was built from.

Parameters:

Name Type Description Default
name str

The resource name, not the file name, where the two differ.

required
uri str | PathLike

Where it came from. A readable local path is hashed.

None
checksum str | bool

True hashes uri; False records none; a string is used as given.

True
**fields Any

format, version, reader, and anything else worth keeping.

{}

Returns:

Type Description
dict

The record as stored.

records
records()

Every source record, as dicts, in the order they were read.