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 accessorsnx,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,hyperornode_edge;directed: the direction, separate from the kind;ml_kind: the place in a multilayer graph,intra,interorcoupling. For a graph without layers, it isintra.
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
|
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"
|
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: |
{}
|
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
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 |
Examples:
E
property
The edge sequence.
Returns:
| Type | Description |
|---|---|
EdgeSequence
|
The edges in graph order, with the same keys as :attr: |
Examples:
shape
property
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: |
is_multilayer
property
Whether the graph has declared multilayer aspects.
Returns:
| Type | Description |
|---|---|
bool
|
|
nv_supra
property
Number of supra-nodes (rows of the supra-incidence matrix).
Returns:
| Type | Description |
|---|---|
int
|
Count of entities whose internal kind is |
supra_shape
property
Supra-matrix shape as (nv_supra, len(anet.E)).
Returns:
| Type | Description |
|---|---|
tuple[int, int]
|
Supra-incidence row count and edge count. |
attrs
property
The eight attribute addresses, read and written one way.
Returns:
| Type | Description |
|---|---|
Attrs
|
Reads return detached copies: |
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
Graph-level unstructured metadata.
Returns:
| Type | Description |
|---|---|
dict
|
Mutable dictionary of graph-level attributes. |
provenance
property
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:
A
property
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
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
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
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
Return the graph Laplacian, the degree matrix minus the adjacency.
Returns:
| Type | Description |
|---|---|
sparray
|
Every row sums to zero. |
matrices
property
Return the parameterized-matrix namespace of this graph.
Returns:
| Type | Description |
|---|---|
MatrixNamespace
|
|
idx
property
Index lookup namespace.
Returns:
| Type | Description |
|---|---|
IndexManager
|
Manager for entity-to-row and edge-to-column index lookups. |
cache
property
Sparse matrix cache namespace.
Returns:
| Type | Description |
|---|---|
CacheManager
|
Manager for derived sparse matrix formats such as CSR and CSC. |
slices
property
Slice operations namespace.
Returns:
| Type | Description |
|---|---|
SliceManager
|
Manager exposing slice creation, membership, set operations, and slice-level analysis. |
Examples:
layers
property
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:
ops
property
Structural operations namespace.
Returns:
| Type | Description |
|---|---|
OperationsAccessor
|
Manager for subgraphs, copies, reversals, incidence extraction, and memory inspection. |
Examples:
history
property
Mutation history and snapshot namespace.
Returns:
| Type | Description |
|---|---|
HistoryAccessor
|
Callable namespace: |
Examples:
nx
property
ig
property
Igraph interoperability namespace.
Returns:
| Type | Description |
|---|---|
_IGBackendAccessor
|
Lazy proxy that converts to igraph only when requested. |
gt
property
graph-tool interoperability namespace.
Returns:
| Type | Description |
|---|---|
_GTBackendAccessor
|
Lazy proxy that converts to graph-tool only when requested. |
Functions
add_nodes
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:
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 |
{}
|
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
|
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:
add_edges
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:
|
()
|
**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 |
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 |
parallel |
('update', 'error', 'parallel')
|
Policy for single-edge insertion when |
propagate |
('none', 'shared', 'all')
|
Slice propagation policy. |
flexible |
dict
|
Data-driven direction policy. Requires keys |
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:
remove_nodes
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"
|
Returns:
| Type | Description |
|---|---|
None
|
|
Notes
Incident edges are removed with each node.
Examples:
remove_edges
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"
|
Returns:
| Type | Description |
|---|---|
None
|
|
Examples:
make_undirected
Convert all existing edges to undirected form in place.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
drop_flexible
|
bool
|
If |
True
|
update_default
|
bool
|
If |
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:
has_node
Check whether a node exists.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
node_id
|
str | tuple
|
Bare node ID, or explicit |
required |
Returns:
| Type | Description |
|---|---|
bool
|
|
Notes
In multilayer graphs, a bare node ID returns True if that node
is present on at least one layer coordinate.
has_edge
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 |
Raises:
| Type | Description |
|---|---|
ValueError
|
If the argument combination is invalid. |
Examples:
degree
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 |
neighbors
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
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
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
Alias for :meth:in_neighbors.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
node_id
|
str
|
Node identifier. |
required |
Returns:
| Type | Description |
|---|---|
list[str]
|
Predecessor identifiers. |
successors
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
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"
|
Returns:
| Type | Description |
|---|---|
list[tuple[int, EdgeView]]
|
Pairs of |
Raises:
| Type | Description |
|---|---|
ValueError
|
If |
Examples:
edge_list
Materialize binary edges as endpoint tuples.
Returns:
| Type | Description |
|---|---|
list[tuple[str, str, str, float]]
|
Tuples of |
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
Count unique members present across slices.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
kind
|
('nodes', 'edges', 'entities')
|
Membership domain. |
"nodes"
|
Returns:
| Type | Description |
|---|---|
int
|
Number of unique members observed in slice membership. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If |
Notes
This is a slice-membership count, not a storage count. For graph
storage counts, use :meth:ncount and :meth:ecount.
at
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
|
|
Raises:
| Type | Description |
|---|---|
KeyError
|
If an aspect is unknown or unnamed, or if the node is not on that
node-layer. Use :meth: |
Examples:
exists
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 |
Examples:
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
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
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 |
None
|
edges
|
id | Iterable | EdgeSequence | RowSelection
|
Edge ids or a |
None
|
layers
|
coordinate | Iterable | LayerSelection | RowSelection
|
One layer coordinate, a collection of them, |
None
|
slices
|
id | Iterable | SliceMembership
|
One slice id or several (their union), or the membership a slice
operation such as |
None
|
predicate
|
callable
|
A node-id predicate, the advanced escape hatch. Its exceptions propagate with the offending id. |
None
|
boundary
|
('closed', 'open')
|
|
"closed"
|
Returns:
| Type | Description |
|---|---|
GraphView
|
Live against this graph, read-only, and narrowed further with
|
read
classmethod
Read a graph from the native .annnet format.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
path
|
str | Path
|
Input file path. |
required |
**kwargs
|
Passed to |
{}
|
Returns:
| Type | Description |
|---|---|
AnnNet
|
Deserialized graph. |
Examples:
write
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, |
False
|
**kwargs
|
Passed to |
{}
|
Returns:
| Type | Description |
|---|---|
None
|
|
Examples:
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:
annnet.core._records.as_endpoint
annnet.core._records.as_endpoints
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: |
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
record
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
|
**fields
|
Any
|
|
{}
|
Returns:
| Type | Description |
|---|---|
dict
|
The record as stored. |