Layers
Multilayer helpers from annnet.core._Layers.
Use G.layers and the AnnNet layer methods for layer workflows. Direct
imports from underscore modules follow the internal API policy.
annnet.core._Layers.LayerAccessor
Namespace for multilayer operations on an :class:~annnet.core.graph.AnnNet graph.
Functions
list_layers
Return the user-declared layers, omitting the '_' placeholder by default.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
aspect
|
str | None
|
If given, return a sorted list for that single aspect. |
None
|
include_placeholder
|
bool
|
Include the synthetic |
False
|
__dir__
The layer operations, and not the fields of the graph behind them.
__getattr__ forwards every unknown name to the graph, __dict__
included, so the default dir() reported the graph's whole instance
state as though it were part of this namespace — graph_attributes and
node_aligned among them, neither of which is an operation.
set_aspects
Define multi-aspect structure.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
aspects
|
list[str]
|
Aspect identifiers (e.g., |
required |
elem_layers
|
dict[str, list[str]]
|
Elementary labels per aspect (e.g., |
None
|
Returns:
| Type | Description |
|---|---|
None
|
|
Raises:
| Type | Description |
|---|---|
ValueError
|
If |
Examples:
aspect
Return one aspect, with its values in declaration order.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
name
|
str
|
The aspect. |
required |
Returns:
| Type | Description |
|---|---|
Aspect
|
Its values, and whether they come one before another. |
Raises:
| Type | Description |
|---|---|
KeyError
|
If the aspect is not declared. |
Examples:
values
Return the resolver that answers for node-layer values.
Returns:
| Type | Description |
|---|---|
ValueResolver
|
The contextual store first, then every attached array in the order it was attached. A later backing wins for a cell it can answer. |
attach_values
Attach an array of node-layer values without copying a cell.
The contextual store keys every value by its pair, which costs about 360 bytes a cell. That is the right shape for values a person typed and the wrong one for values that arrived as a table. Attaching costs the two index maps and nothing else: the array is not copied, not converted, and not read until a cell is asked for.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
arrays
|
dict[str, array - like]
|
One two-dimensional array per attribute name, |
required |
layers
|
Sequence[tuple[str, ...]]
|
The layer each row stands for, in row order. |
required |
nodes
|
Sequence[str]
|
The node each column stands for, in column order. |
required |
rows
|
dict
|
Explicit index maps. An explicit column map lets two nodes share one column without the column being copied. |
None
|
columns
|
dict
|
Explicit index maps. An explicit column map lets two nodes share one column without the column being copied. |
None
|
mask
|
array - like
|
A boolean array gating which cells hold a value at all. |
None
|
Returns:
| Type | Description |
|---|---|
MatrixValues
|
The backing, so a caller can detach it later. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If |
Examples:
detach_values
Drop one attached array. The contextual store is never dropped.
matrix
Read one attribute as an array, with the labels that index it.
This is what to hand a method. A frame of Python objects has to be unpacked before any arithmetic; an array is the arithmetic's own shape, and the two label lists are what put an answer back on the right rows.
Where the values live in an attached array this reads them in one pass in C. Where they live in the dict store, or span both, it falls back to reading cell by cell — and the two give the same numbers, which is pinned by test.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
name
|
str
|
The attribute. |
required |
nodes
|
Sequence[str]
|
The node of each column. Default: every node carrying a value, sorted. |
None
|
layers
|
Sequence[tuple[str, ...]]
|
The layer of each row. Default: every layer carrying one, in the order the graph declares them. |
None
|
missing
|
Any
|
What a cell no backing answers for holds. |
``numpy.nan``
|
Returns:
| Type | Description |
|---|---|
ValueMatrix
|
|
Examples:
node_frame
node_frame(
nodes=None,
layers=None,
attrs=None,
*,
pairs=None,
format="wide",
missing=nan,
backend=None
)
Read node-layer values as a table.
The scalar accessor :meth:node_attrs answers for one pair and returns a
dict, so reading a node by layer by attribute cube meant a Python loop
with a .get() default in it — a helper every analysis wrote for
itself. This is that cube.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
nodes
|
Sequence[str]
|
Node ids. Default: every node that carries a value. |
None
|
layers
|
Sequence[tuple[str, ...]]
|
Layer coordinates. Default: every layer that carries a value, in the order the graph declares them. |
None
|
attrs
|
Sequence[str]
|
Attribute names. Default: every name present. |
None
|
pairs
|
Mapping[str, tuple[str, str]] | Sequence[tuple[str, str]]
|
Explicit |
None
|
format
|
('wide', 'long')
|
|
"wide"
|
missing
|
Any
|
What a cell no backing answers for holds. Never a |
``numpy.nan``
|
backend
|
str
|
Dataframe backend. Defaults to the graph's. |
None
|
Returns:
| Type | Description |
|---|---|
DataFrame - like
|
In |
Raises:
| Type | Description |
|---|---|
ValueError
|
If |
Notes
Values are read through :meth:matrix, so an attached array is gathered
in one pass rather than a cell at a time, and the frame is the same
whichever store answered.
Examples:
place
Put every node on every layer, in one call.
Identity and values are separate questions, and this is the identity one. The value of a node-layer may live in an attached array, which costs two index maps; its presence still lives in the structure store, and placing a rectangle one pair at a time is what makes a real measurement table slow to attach whatever its values do.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
nodes
|
Sequence[str]
|
The node ids to place. |
required |
layers
|
Sequence[tuple[str, ...]]
|
The layer coordinates to place them on. |
required |
mask
|
array - like
|
A boolean array, |
None
|
Returns:
| Type | Description |
|---|---|
int
|
The number of node-layers created. |
Examples:
set_node_attrs_bulk
Write many node-layer values in one call.
The scalar :meth:set_node_attrs takes one pair, so filling a table
meant a loop with a call in it.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
values
|
Mapping
|
One of three shapes:
|
required |
layer
|
tuple[str, ...]
|
The layer, when the keys are bare node ids. |
None
|
key
|
str
|
The attribute name, when the values are scalars. |
None
|
Returns:
| Type | Description |
|---|---|
int
|
The number of pairs written. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If a key is a bare node id and no |
Examples:
where
Select the layers whose aspect values satisfy every predicate.
A predicate is aspect=value or aspect__operator=value. The
operators are eq (the default), ne, in, not_in, lt,
lte, gt and gte. The last four ask where a value sits, so
they need an ordered aspect and refuse a categorical one — the answer
would otherwise be the declaration order pretending to be a meaning.
The window is resolved off the aspect declaration, so it costs the number
of layers rather than the size of the graph. What it is then asked for —
.nodes, .edges, .crossing, .boundary — costs one pass
over the axis in question.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
**predicates
|
One or more |
{}
|
Returns:
| Type | Description |
|---|---|
LayerSelection
|
|
Raises:
| Type | Description |
|---|---|
KeyError
|
If an aspect is not declared. |
ValueError
|
If an operator is unknown, or a comparison is asked of a categorical aspect. |
Examples:
set_ordered
Declare whether one aspect's values come one before another.
An ordinal aspect — a timepoint, a dose, a stage — answers before,
after and consecutive_pairs, and can be windowed with the
comparison predicates of :meth:where. A categorical one refuses them,
because the answer would be the declaration order pretending to be a
meaning.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
name
|
str
|
The aspect. |
required |
ordered
|
bool
|
|
True
|
Raises:
| Type | Description |
|---|---|
KeyError
|
If the aspect is not declared. |
Examples:
set_elementary_layers
Declare concrete elementary layer values for existing aspects.
augment_elementary_layers
Add layer values to the aspects the graph already declares.
This is not :meth:set_elementary_layers, because that helper drops an
unused placeholder layer. A restore needs the '_' placeholder to
survive, or a coordinate the file stored against it stops validating.
An aspect the graph does not declare is ignored.
flatten_layers
Remove multilayer structure in-place and project to a flat graph.
Returns:
| Type | Description |
|---|---|
AnnNet
|
The mutated graph itself. |
Notes
This projects node identities from (node_id, layer_tuple) to bare
node_id strings and drops multilayer-only metadata such as aspects,
layer registries, supra-node attributes, and multilayer edge roles.
add_elementary_layer
Register a new elementary layer label under an existing aspect.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
aspect
|
str
|
Existing aspect name. |
required |
label
|
str
|
New elementary layer label. |
required |
Returns:
| Type | Description |
|---|---|
None
|
|
has_presence
Check whether the graph holds the entity (u, aa).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
u
|
str
|
Node identifier. |
required |
layer_tuple
|
tuple[str, ...]
|
Aspect tuple layer. |
required |
Returns:
| Type | Description |
|---|---|
bool
|
|
iter_layers
Iterate over all aspect-tuples (Cartesian product).
Yields:
| Type | Description |
|---|---|
tuple[str, ...]
|
Layer tuples in configured order. |
iter_node_layers
Iterate layer tuples where (u, aa) is in V_M.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
u
|
str
|
Node identifier. |
required |
Yields:
| Type | Description |
|---|---|
tuple[str, ...]
|
Layer tuples for |
ensure_node_layer_index
Return the number of indexed node–layer pairs.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
restrict_layers
|
list[tuple[str, ...]] | None
|
If provided, count only these layers. |
None
|
Returns:
| Type | Description |
|---|---|
int
|
Number of indexed node–layer pairs. |
Notes
Kept for backward compatibility. Use _build_supra_index() internally.
nl_to_row
Map (u, aa) to row index.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
u
|
str
|
Node identifier. |
required |
layer_tuple
|
tuple[str, ...]
|
Aspect tuple layer. |
required |
Returns:
| Type | Description |
|---|---|
int
|
|
Raises:
| Type | Description |
|---|---|
KeyError
|
If the node–layer pair is not indexed. |
row_to_nl
Map row index to (u, aa).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
row
|
int
|
Row index. |
required |
Returns:
| Type | Description |
|---|---|
tuple[str, tuple[str, ...]]
|
|
Raises:
| Type | Description |
|---|---|
KeyError
|
If the row is not indexed. |
layer_id_to_tuple
Map legacy string layer id to aspect tuple.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
layer_id
|
str
|
Layer identifier (single-aspect only). |
required |
Returns:
| Type | Description |
|---|---|
tuple[str, ...]
|
|
Raises:
| Type | Description |
|---|---|
ValueError
|
If not in single-aspect mode. |
layer_tuple_to_id
Canonical string id for a layer tuple.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
aa
|
tuple[str, ...]
|
Aspect tuple layer. |
required |
Returns:
| Type | Description |
|---|---|
str
|
Canonical id (single label for 1 aspect, or |
set_elementary_attrs
Attach attributes to an elementary Kivela layer.
aspect and label are positional-only so user attribute
keys (including label=) are passed through verbatim.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
aspect
|
str
|
Aspect identifier (positional-only). |
required |
label
|
str
|
Elementary layer label (positional-only). |
required |
**attrs
|
Key-value metadata to store. |
{}
|
Returns:
| Type | Description |
|---|---|
None
|
|
elementary_attrs
Get attributes for an elementary Kivela layer.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
aspect
|
str
|
Aspect identifier. |
required |
label
|
str
|
Elementary layer label. |
required |
Returns:
| Type | Description |
|---|---|
dict
|
Attributes dict; empty if not set. |
set_aspect_attrs
Attach metadata to a Kivela aspect.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
aspect
|
str
|
Aspect identifier. |
required |
**attrs
|
Key-value metadata to store. |
{}
|
Returns:
| Type | Description |
|---|---|
None
|
|
aspect_attrs
Return a shallow copy of metadata for a Kivela aspect.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
aspect
|
str
|
Aspect identifier. |
required |
Returns:
| Type | Description |
|---|---|
dict
|
|
set_attrs
Attach metadata to a Kivela layer.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
layer_tuple
|
tuple[str, ...]
|
Aspect tuple layer. |
required |
**attrs
|
Key-value metadata to store. |
{}
|
Returns:
| Type | Description |
|---|---|
None
|
|
attrs
Get metadata dict for a Kivela layer.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
layer_tuple
|
tuple[str, ...]
|
Aspect tuple layer. |
required |
Returns:
| Type | Description |
|---|---|
dict
|
Shallow copy; empty if not set. |
set_node_attrs
Attach metadata to a node–layer pair.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
u
|
str
|
Node identifier. |
required |
layer_tuple
|
tuple[str, ...]
|
Aspect tuple layer. |
required |
**attrs
|
Key-value metadata to store. |
{}
|
Returns:
| Type | Description |
|---|---|
None
|
|
Raises:
| Type | Description |
|---|---|
KeyError
|
If |
node_attrs
Get metadata dict for a node–layer pair.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
u
|
str
|
Node identifier. |
required |
layer_tuple
|
tuple[str, ...]
|
Aspect tuple layer. |
required |
Returns:
| Type | Description |
|---|---|
dict
|
Shallow copy; empty if not set. |
layer_node_set
Nodes present in a Kivela layer.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
layer_tuple
|
Iterable[str]
|
Aspect tuple layer. |
required |
Returns:
| Type | Description |
|---|---|
set[str]
|
|
layer_edge_set
Edges associated with a Kivela layer.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
layer_tuple
|
Iterable[str]
|
Aspect tuple layer. |
required |
include_inter
|
bool
|
Include inter-layer edges touching |
False
|
include_coupling
|
bool
|
Include coupling edges touching |
False
|
Returns:
| Type | Description |
|---|---|
set[str]
|
Every edge touching this layer. This is the primitive the layer
algebra is built on, and it carries no |
layer_union
Union of several Kivela layers.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
layer_tuples
|
Iterable[Iterable[str]]
|
Layer tuples to union. |
required |
include_inter
|
bool
|
Include inter-layer edges touching any layer in the union. |
False
|
include_coupling
|
bool
|
Include coupling edges touching any layer in the union. |
False
|
boundary
|
('closed', 'open')
|
|
"closed"
|
Returns:
| Type | Description |
|---|---|
dict
|
|
Notes
With the default include_inter=False and include_coupling=False
the two boundaries agree, because an intra-layer edge never leaves its
layer. They differ exactly when a crossing edge was asked for.
layer_intersection
layer_intersection(
layer_tuples,
*,
include_inter=False,
include_coupling=False,
boundary="closed"
)
Intersection of several Kivela layers.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
layer_tuples
|
Iterable[Iterable[str]]
|
Layer tuples to intersect. |
required |
include_inter
|
bool
|
Include inter-layer edges touching any layer in the intersection. |
False
|
include_coupling
|
bool
|
Include coupling edges touching any layer in the intersection. |
False
|
boundary
|
('closed', 'open')
|
|
"closed"
|
Returns:
| Type | Description |
|---|---|
dict
|
|
Notes
An intra-layer edge belongs to one layer, so it cannot be in the intersection of two. What survives here is a crossing edge that touches every named layer, and only when one was asked for.
layer_difference
layer_difference(
layer_a,
layer_b,
*,
include_inter=False,
include_coupling=False,
boundary="closed"
)
Set difference: elements in layer_a but not in layer_b.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
layer_a
|
Iterable[str]
|
Minuend layer tuple. |
required |
layer_b
|
Iterable[str]
|
Subtrahend layer tuple. |
required |
include_inter
|
bool
|
Include inter-layer edges touching |
False
|
include_coupling
|
bool
|
Include coupling edges touching |
False
|
boundary
|
('closed', 'open')
|
|
"closed"
|
Returns:
| Type | Description |
|---|---|
dict
|
|
create_slice_from_layer
create_slice_from_layer(
slice_id,
layer_tuple,
*,
include_inter=False,
include_coupling=False,
boundary="closed",
**attributes
)
Create a slice induced by a single Kivela layer.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
slice_id
|
str
|
Slice identifier. |
required |
layer_tuple
|
Iterable[str]
|
Layer tuple. |
required |
include_inter
|
bool
|
Include inter-layer edges touching |
False
|
include_coupling
|
bool
|
Include coupling edges touching |
False
|
boundary
|
('closed', 'open')
|
|
"closed"
|
**attributes
|
Slice attributes to store. |
{}
|
Returns:
| Type | Description |
|---|---|
str
|
The created slice id. |
Examples:
create_slice_from_layer_union
create_slice_from_layer_union(
slice_id,
layer_tuples,
*,
include_inter=False,
include_coupling=False,
**attributes
)
Create a slice as the union of several layers.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
slice_id
|
str
|
Slice identifier. |
required |
layer_tuples
|
Iterable[Iterable[str]]
|
Layer tuples to union. |
required |
include_inter
|
bool
|
Include inter-layer edges touching any layer in the union. |
False
|
include_coupling
|
bool
|
Include coupling edges touching any layer in the union. |
False
|
**attributes
|
Slice attributes to store. |
{}
|
Returns:
| Type | Description |
|---|---|
str
|
The created slice id. |
create_slice_from_layer_intersection
create_slice_from_layer_intersection(
slice_id,
layer_tuples,
*,
include_inter=False,
include_coupling=False,
**attributes
)
Create a slice as the intersection of several layers.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
slice_id
|
str
|
Slice identifier. |
required |
layer_tuples
|
Iterable[Iterable[str]]
|
Layer tuples to intersect. |
required |
include_inter
|
bool
|
Include inter-layer edges touching any layer in the intersection. |
False
|
include_coupling
|
bool
|
Include coupling edges touching any layer in the intersection. |
False
|
**attributes
|
Slice attributes to store. |
{}
|
Returns:
| Type | Description |
|---|---|
str
|
The created slice id. |
create_slice_from_layer_difference
create_slice_from_layer_difference(
slice_id,
layer_a,
layer_b,
*,
include_inter=False,
include_coupling=False,
**attributes
)
Create a slice as the difference of two layers.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
slice_id
|
str
|
Slice identifier. |
required |
layer_a
|
Iterable[str]
|
Minuend layer tuple. |
required |
layer_b
|
Iterable[str]
|
Subtrahend layer tuple. |
required |
include_inter
|
bool
|
Include inter-layer edges touching |
False
|
include_coupling
|
bool
|
Include coupling edges touching |
False
|
**attributes
|
Slice attributes to store. |
{}
|
Returns:
| Type | Description |
|---|---|
str
|
The created slice id. |
subgraph_from_layer_tuple
subgraph_from_layer_tuple(
layer_tuple,
*,
include_inter=False,
include_coupling=False,
boundary="closed"
)
Concrete subgraph induced by a single Kivela layer.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
layer_tuple
|
Iterable[str]
|
Layer tuple. |
required |
include_inter
|
bool
|
Include inter-layer edges touching |
False
|
include_coupling
|
bool
|
Include coupling edges touching |
False
|
boundary
|
('closed', 'open')
|
|
"closed"
|
Returns:
| Type | Description |
|---|---|
AnnNet
|
|
subgraph_from_layer_union
subgraph_from_layer_union(
layer_tuples,
*,
include_inter=False,
include_coupling=False,
boundary="closed"
)
Concrete subgraph induced by the union of several layers.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
layer_tuples
|
Iterable[Iterable[str]]
|
Layer tuples to union. |
required |
include_inter
|
bool
|
Include inter-layer edges touching any layer in the union. |
False
|
include_coupling
|
bool
|
Include coupling edges touching any layer in the union. |
False
|
boundary
|
('closed', 'open')
|
|
"closed"
|
Returns:
| Type | Description |
|---|---|
AnnNet
|
|
subgraph_from_layer_intersection
Concrete subgraph induced by the intersection of several layers.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
layer_tuples
|
Iterable[Iterable[str]]
|
Layer tuples to intersect. |
required |
include_inter
|
bool
|
Include inter-layer edges touching any layer in the intersection. |
False
|
include_coupling
|
bool
|
Include coupling edges touching any layer in the intersection. |
False
|
Returns:
| Type | Description |
|---|---|
AnnNet
|
|
subgraph_from_layer_difference
Concrete subgraph induced by a set-difference of two layers.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
layer_a
|
Iterable[str]
|
Minuend layer tuple. |
required |
layer_b
|
Iterable[str]
|
Subtrahend layer tuple. |
required |
include_inter
|
bool
|
Include inter-layer edges touching |
False
|
include_coupling
|
bool
|
Include coupling edges touching |
False
|
Returns:
| Type | Description |
|---|---|
AnnNet
|
|
supra_adjacency
Build the supra adjacency matrix.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
layers
|
list[str] | list[tuple[str, ...]] | None
|
Optional subset of layers. In single-aspect mode, string ids are accepted. |
None
|
Returns:
| Type | Description |
|---|---|
csr_matrix
|
Supra adjacency over the chosen node–layer index. |
Examples:
supra_incidence
Build the supra-incidence matrix over selected layers.
Unlike supra_adjacency, this preserves the full hyperedge structure —
a k-ary hyperedge becomes a single column with k nonzero entries, with
stoichiometric coefficients intact. Binary intra, inter, coupling, and
hyperedges are all handled in a unified column-oriented representation.
Rows : node-layer pairs (u, aa) — identical index to supra_adjacency,
built by ensure_node_layer_index.
Cols : one per selected edge, ordered as: intra edges (per layer, sorted
by eid), then inter/coupling edges, then unassigned hyperedges last.
Column sign convention (matches _matrix):
- Binary directed : +w at source row, -w at target row
- Binary undirected : +w at both rows
- Hyperedge directed: +w at head rows, -w at tail rows (stoich-aware)
- Hyperedge undirected: +w at all member rows (stoich-aware)
- Inter/coupling : +w at (u, La) row, -w at (v, Lb) row (directed)
Hyperedges MUST have a layer assignment in edge_layers (set via
set_edge_kivela_role(eid, "intra", layer_tuple) after add_hyperedge).
Hyperedges without a layer assignment are collected in the returned
skipped list and excluded from the matrix — they do NOT silently corrupt
the result.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
layers
|
list[str] | list[tuple[str, ...]] | None
|
Optional subset of layers. None = all layers in V_M. Single-aspect string ids are accepted. |
None
|
include_inter
|
bool
|
Include inter-layer edges in the output columns. Default True. |
True
|
include_coupling
|
bool
|
Include coupling edges in the output columns. Default True. |
True
|
Returns:
| Name | Type | Description |
|---|---|---|
B |
csr_matrix
|
Shape (|V_M|, |E_selected|). Rows are node-layer pairs in the order given by self._row_to_nl after ensure_node_layer_index. |
edge_ids |
list[str]
|
Edge id for each column of B, in column order. Use this to map columns back to edges for interpretability. |
skipped |
list[str]
|
Edge ids that were excluded because their layer assignment could not be resolved. Inspect these if B looks sparse. |
Notes
The hypergraph random-walk diffusion operator follows directly::
B_csr = B (this output)
D_v = diag(|B| @ ones) # node degree (sum of |entries| per row)
D_e = diag(|B|.T @ ones) # edge degree (sum of |entries| per col)
Theta = D_v_inv @ B @ D_e_inv @ B.T
Examples:
build_intra_block
Supra matrix containing only intra-layer edges (diagonal blocks).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
layers
|
list[str] | list[tuple[str, ...]] | None
|
Optional subset of layers. |
None
|
Returns:
| Type | Description |
|---|---|
csr_matrix
|
|
build_inter_block
Supra matrix containing only inter-layer (non-diagonal) edges.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
layers
|
list[str] | list[tuple[str, ...]] | None
|
Optional subset of layers. |
None
|
Returns:
| Type | Description |
|---|---|
csr_matrix
|
|
build_coupling_block
Supra matrix containing only coupling edges.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
layers
|
list[str] | list[tuple[str, ...]] | None
|
Optional subset of layers. |
None
|
Returns:
| Type | Description |
|---|---|
csr_matrix
|
|
supra_degree
Degree vector over the supra-graph.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
layers
|
list[str] | list[tuple[str, ...]] | None
|
Optional subset of layers. |
None
|
Returns:
| Type | Description |
|---|---|
ndarray
|
|
supra_laplacian
Build supra-Laplacian.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
kind
|
str
|
|
'comb'
|
layers
|
list[str] | list[tuple[str, ...]] | None
|
Optional subset of layers. |
None
|
Returns:
| Type | Description |
|---|---|
csr_matrix
|
|
couple
couple(
aspect,
*,
kind="ordinal",
pairs=None,
within=None,
on=None,
edge_kind=None,
weight=1.0,
directed=False,
both_present=True
)
Couple the layers of one aspect, in one call.
A multilayer graph has two families of coupling and they follow from
whether the aspect is ordered. An ordinal aspect couples consecutive
values — a timepoint to the next timepoint. A categorical one couples
across values — every mechanism to every other. Both were reachable
before only by building the value pairs by hand from a list kept beside
the graph, which is the fact :meth:aspect now holds.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
aspect
|
str
|
The aspect to couple along. |
required |
kind
|
('ordinal', 'categorical')
|
Which family. |
"ordinal"
|
pairs
|
Sequence[tuple[str, str]]
|
Explicit value pairs on this aspect, for a coupling neither family describes. |
None
|
within
|
dict
|
Restrict to layers whose other aspects match, as
|
None
|
on
|
str
|
A node attribute two different node ids may share when they denote one entity — a shared symbol, where the same thing is measured two ways and each way names it differently. Default: couple a node to itself. |
None
|
edge_kind
|
str
|
The family name carried in the edge id and in the |
None
|
weight
|
float
|
|
1.0
|
directed
|
bool
|
|
False
|
both_present
|
bool
|
Couple only where both node-layers already exist. |
True
|
Returns:
| Type | Description |
|---|---|
int
|
The number of coupling edges added. |
Raises:
| Type | Description |
|---|---|
KeyError
|
If the aspect is not declared, or a pair names a value it does not hold. |
ValueError
|
If |
Examples:
add_layer_coupling_pairs
Add diagonal couplings for explicit layer pairs.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
layer_pairs
|
list[tuple[tuple[str, ...], tuple[str, ...]]]
|
Layer tuple pairs |
required |
weight
|
float
|
Edge weight. |
1.0
|
edge_kind
|
str
|
The family name carried in the edge id and in the |
None
|
Returns:
| Type | Description |
|---|---|
int
|
Number of edges added. |
add_categorical_coupling
Add categorical couplings along one aspect.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
aspect
|
str
|
Aspect name to couple over. |
required |
groups
|
list[list[str]]
|
Groups of elementary labels to fully connect per node. |
required |
weight
|
float
|
Edge weight. |
1.0
|
edge_kind
|
str
|
The family name carried in the edge id and in the |
None
|
Returns:
| Type | Description |
|---|---|
int
|
Number of edges added. |
add_diagonal_coupling_filter
Add diagonal couplings within a filtered layer subspace.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
layer_filter
|
dict[str, set]
|
Aspect filters (e.g., |
required |
weight
|
float
|
Edge weight. |
1.0
|
edge_kind
|
str
|
The family name carried in the edge id and in the |
None
|
Returns:
| Type | Description |
|---|---|
int
|
Number of edges added. |
tensor_index
adjacency_tensor_view
Sparse 4-index adjacency view.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
layers
|
list[str] | list[tuple[str, ...]] | None
|
Optional subset of layers. |
None
|
Returns:
| Type | Description |
|---|---|
dict
|
|
Notes
Symmetric entries are emitted twice: (ui, ai, vi, bi) and (vi, bi, ui, ai).
flatten_to_supra
Flatten a tensor view into a supra adjacency matrix.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
tensor_view
|
dict
|
Output of :meth: |
required |
Returns:
| Type | Description |
|---|---|
csr_matrix
|
|
unflatten_from_supra
Unflatten a supra adjacency matrix into a tensor view.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
A
|
sparray
|
Supra adjacency matrix. |
required |
layers
|
list[str] | list[tuple[str, ...]] | None
|
Optional subset of layers. |
None
|
Returns:
| Type | Description |
|---|---|
dict
|
Tensor view with the same schema as :meth: |
supra_adjacency_scaled
Build scaled supra adjacency.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
coupling_scale
|
float
|
Scaling factor for coupling edges. |
1.0
|
include_inter
|
bool
|
Whether to include inter-layer edges. |
True
|
layers
|
list[str] | list[tuple[str, ...]] | None
|
Optional subset of layers. |
None
|
Returns:
| Type | Description |
|---|---|
csr_matrix
|
|
transition_matrix
Row-stochastic transition matrix P = D^{-1} A.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
layers
|
list[str] | list[tuple[str, ...]] | None
|
Optional subset of layers. |
None
|
Returns:
| Type | Description |
|---|---|
csr_matrix
|
|
random_walk_step
One random-walk step p' = p P.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
p
|
array - like
|
Row vector of length |
required |
layers
|
list[str] | list[tuple[str, ...]] | None
|
Optional subset of layers. |
None
|
Returns:
| Type | Description |
|---|---|
ndarray
|
|
diffusion_step
One explicit Euler step of diffusion on the supra-graph.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
x
|
array - like
|
State vector of length |
required |
tau
|
float
|
Time step. |
1.0
|
kind
|
str
|
|
'comb'
|
layers
|
list[str] | list[tuple[str, ...]] | None
|
Optional subset of layers. |
None
|
Returns:
| Type | Description |
|---|---|
ndarray
|
|
algebraic_connectivity
Algebraic connectivity of the supra-graph.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
layers
|
list[str] | list[tuple[str, ...]] | None
|
Optional subset of layers. |
None
|
Returns:
| Type | Description |
|---|---|
tuple[float, ndarray | None]
|
|
k_smallest_laplacian_eigs
Return k smallest eigenvalues/eigenvectors of the supra-Laplacian.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
k
|
int
|
Number of eigenpairs to compute. |
6
|
kind
|
str
|
|
'comb'
|
layers
|
list[str] | list[tuple[str, ...]] | None
|
Optional subset of layers. |
None
|
Returns:
| Type | Description |
|---|---|
tuple[ndarray, ndarray]
|
|
dominant_rw_eigenpair
Dominant eigenpair of the random-walk operator.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
layers
|
list[str] | list[tuple[str, ...]] | None
|
Optional subset of layers. |
None
|
Returns:
| Type | Description |
|---|---|
tuple[float, ndarray | None]
|
|
sweep_coupling_regime
Scan coupling scales and evaluate a metric.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
scales
|
Iterable[float]
|
Coupling scales to evaluate. |
required |
metric
|
str | callable
|
|
'algebraic_connectivity'
|
layers
|
list[str] | list[tuple[str, ...]] | None
|
Optional subset of layers. |
None
|
Returns:
| Type | Description |
|---|---|
list[float]
|
Metric values aligned with |
layer_degree_vectors
Per-layer degree vectors (intra-layer only).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
layers
|
list[str] | list[tuple[str, ...]] | None
|
Optional subset of layers. |
None
|
Returns:
| Type | Description |
|---|---|
dict
|
|
participation_coefficient
Participation coefficient per node.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
layers
|
list[str] | list[tuple[str, ...]] | None
|
Optional subset of layers. |
None
|
Returns:
| Type | Description |
|---|---|
dict[str, float]
|
|
versatility
Versatility proxy based on dominant eigenvector of supra adjacency.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
layers
|
list[str] | list[tuple[str, ...]] | None
|
Optional subset of layers. |
None
|
Returns:
| Type | Description |
|---|---|
dict[str, float]
|
|
multislice_modularity
Mucha et al. multislice modularity (scorer only).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
partition
|
array - like
|
Community ids, length |
required |
gamma
|
float
|
Resolution parameter. |
1.0
|
omega
|
float
|
Coupling strength (binary coupling structure scaled by |
1.0
|
include_inter
|
bool
|
Whether to include inter-layer (non-diagonal) edges. |
False
|
layers
|
list[str] | list[tuple[str, ...]] | None
|
Optional subset of layers to score on. |
None
|
Returns:
| Type | Description |
|---|---|
float
|
Modularity score |
Examples:
Aspects
An aspect's values, and whether they come one before another. See Aspects, order, and windows.
annnet.core._aspects.Aspect
One aspect of a multilayer graph, and whether its values are ordered.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
values
|
Sequence[str]
|
The elementary labels, in the order they are meant to be read. |
required |
ordered
|
bool
|
Whether one value comes before another. An ordered aspect answers
:meth: |
False
|
Examples:
>>> time = Aspect(['0h', '1h', '12h', '24h'], ordered=True)
>>> time.index('12h')
2
>>> time.consecutive_pairs()
[('0h', '1h'), ('1h', '12h'), ('12h', '24h')]
>>> time.normalized_position('12h')
0.6666666666666666
>>> time.before('12h')
['0h', '1h']
Functions
index
The position of one value.
Raises:
| Type | Description |
|---|---|
ValueError
|
If this aspect is categorical. |
KeyError
|
If the value is not one of this aspect's. |
consecutive_pairs
Every (value, next value) pair, which is what ordinal coupling couples.
normalized_position
The position of one value scaled onto [0, 1].
A one-value aspect answers 0.0 rather than dividing by zero.
annnet.core._aspects.OrderedLabels
A set of labels that remembers the order they were declared in.
A set was here before, which lost that order: a graph declared with
['basal', 'stim', 'late'] read its layers back as
['basal', 'late', 'stim'], and for an ordinal aspect that is not a
cosmetic difference — it is the wrong order, silently.
A dict is an ordered set with the same membership cost, so this is one
wrapping thin enough to leave every call site unchanged.
annnet.core._aspects.require_boundary
Return value if it names a boundary, and raise otherwise.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
value
|
str
|
|
required |
Returns:
| Type | Description |
|---|---|
str
|
|
Raises:
| Type | Description |
|---|---|
ValueError
|
If |
annnet.core._aspects.as_aspect
Layer selection
annnet.core._selection.LayerSelection
The layers one window names, and what sits on them.
Built by :meth:LayerAccessor.where. Iterating it gives the layer
coordinates; the four properties answer the questions a window is usually
asked, each in one pass.
Attributes:
| Name | Type | Description |
|---|---|---|
layers |
tuple[tuple[str, ...], ...]
|
The coordinates in the window, in the graph's declaration order. |
Attributes
node_layers
property
The (node_id, layer) keys on these layers.
The distinction from :attr:nodes matters as soon as one node sits on
two of the selected layers, which is the ordinary case.
edges
property
The ids of the edges whose every endpoint is on these layers.
Closed: an edge with one endpoint outside the window is not in it. What
that leaves out is :attr:crossing.
annnet.core._selection.parse_predicate
Split one aspect__op keyword into its aspect and its operator.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
key
|
str
|
|
required |
aspects
|
Sequence[str]
|
The declared aspects, for the error message and to keep an aspect whose
own name contains |
required |
Returns:
| Type | Description |
|---|---|
tuple[str, str]
|
|
Raises:
| Type | Description |
|---|---|
KeyError
|
If the aspect is not declared. |
ValueError
|
If the operator is not one of :data: |
annnet.core._selection.satisfies
Whether one layer's value for one aspect satisfies one predicate.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
aspect
|
Aspect
|
The aspect the value belongs to; consulted for order. |
required |
operator
|
str
|
One of :data: |
required |
value
|
Any
|
What this layer holds for the aspect. |
required |
wanted
|
Any
|
What the predicate asked for. |
required |
Returns:
| Type | Description |
|---|---|
bool
|
|
Raises:
| Type | Description |
|---|---|
ValueError
|
If a comparison in :data: |
Node-layer values
The two backings a value may live in, the resolver over them, and the array a method is handed. See Node-layer values and scale.
annnet.core._values.ValueMatrix
dataclass
One attribute, as an array and the two labels that index it.
What a method wants when it is handed a graph. A frame of Python objects has to be unpacked before any arithmetic; this is the arithmetic's own shape, plus the labels needed to put an answer back.
Attributes:
| Name | Type | Description |
|---|---|---|
values |
ndarray
|
|
nodes |
list[str]
|
The node of each column, in order. |
layers |
list[tuple]
|
The layer of each row, in order. |
name |
str
|
The attribute read. |
annnet.core._values.MatrixValues
An array of values, addressed by two index maps.
One array per attribute name, laid out layer by node, plus the two maps that say which row is which layer and which column is which node. That is the shape a measurement table already has, so attaching one costs building the maps and nothing else — no cell is copied, and the array stays whatever it was.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
arrays
|
dict[str, array - like]
|
One two-dimensional array per attribute name, each |
required |
layers
|
Sequence[tuple]
|
The layer each row stands for, in row order. |
required |
nodes
|
Sequence[str]
|
The node each column stands for, in column order. |
required |
rows
|
dict
|
Explicit index maps, when the defaults from |
None
|
columns
|
dict
|
Explicit index maps, when the defaults from |
None
|
mask
|
array - like
|
A boolean array the same shape as the values. A cell it gates out holds no value whatever the array carries there. |
None
|
Raises:
| Type | Description |
|---|---|
ValueError
|
If |
Functions
block
(values, answered) for one rectangle, read straight off the array.
This is what the array was attached for. The per-cell path costs a few microseconds a cell and dominates any read of a real measurement table; fancy-indexing the same cells costs one pass in C.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
nodes
|
Sequence[str]
|
The node of each column, in order. |
required |
layers
|
Sequence[tuple]
|
The layer of each row, in order. |
required |
name
|
str
|
The attribute. |
required |
Returns:
| Type | Description |
|---|---|
tuple[ndarray, ndarray] | None
|
The values, and a boolean array of which cells this backing actually
answers for. |
annnet.core._values.ContextualValues
The contextual store, read as a backing.
Canonical for values a caller sets one at a time through
:meth:LayerAccessor.set_node_attrs. A pair carrying nothing occupies
nothing, which is what makes it right for a sparse, hand-written table and
wrong for a dense one.
annnet.core._values.ValueResolver
Every backing of one graph, asked in order.
A later backing wins for a cell it can answer, so attaching a table shadows whatever the contextual store held for the same pair rather than blending with it. Two sources for one cell is a conflict, and blending would hide it.
Functions
block
One rectangle of values, or None when it cannot be read as one.
Every backing holding name is asked for its rectangle and they are
laid over each other in attachment order, so the same "later wins" rule
:meth:get follows also holds here — including the second backing an
aggregate lands in.
None comes back when some holder has no rectangle to give, which the
dict store never does. It means ask cell by cell, and it is never a
wrong answer.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
nodes
|
Sequence
|
The columns and rows of the rectangle, in order. |
required |
layers
|
Sequence
|
The columns and rows of the rectangle, in order. |
required |
name
|
str
|
The attribute. |
required |
default
|
Any
|
What a cell no backing answers for holds. |
``numpy.nan``
|
Returns:
| Type | Description |
|---|---|
ndarray | None
|
|
annnet.core._values.ValueBacking
One place node-layer values may live.
Functions
get
The value of one cell, or default when this backing has none.