Traversal and History¶
This notebook focuses on two lightweight analysis surfaces:
- neighborhood traversal over binary edges and hyperedges
- mutation history for reproducibility and audit trails
In [1]:
Copied!
from pathlib import Path
import sys
NOTEBOOK_DIR = Path.cwd()
PACKAGE_ROOT = (NOTEBOOK_DIR / "..").resolve()
if str(PACKAGE_ROOT) not in sys.path:
sys.path.insert(0, str(PACKAGE_ROOT))
import annnet as an
from pathlib import Path
import sys
NOTEBOOK_DIR = Path.cwd()
PACKAGE_ROOT = (NOTEBOOK_DIR / "..").resolve()
if str(PACKAGE_ROOT) not in sys.path:
sys.path.insert(0, str(PACKAGE_ROOT))
import annnet as an
In [2]:
Copied!
G = an.AnnNet(directed=None)
G.add_vertices(["Signal", "Kinase", "TF", "Target"])
G.add_edge("Signal", "Kinase", edge_id="e_signal")
G.add_edge("Kinase", "TF", edge_id="e_tf")
G.add_hyperedge(head=["Kinase", "TF"], tail=["Target"], edge_id="he_program")
G.mark("initial_network")
G.add_edge("Target", "Signal", edge_id="feedback", edge_directed=False)
G = an.AnnNet(directed=None)
G.add_vertices(["Signal", "Kinase", "TF", "Target"])
G.add_edge("Signal", "Kinase", edge_id="e_signal")
G.add_edge("Kinase", "TF", edge_id="e_tf")
G.add_hyperedge(head=["Kinase", "TF"], tail=["Target"], edge_id="he_program")
G.mark("initial_network")
G.add_edge("Target", "Signal", edge_id="feedback", edge_directed=False)
Out[2]:
'feedback'
In [3]:
Copied!
print("neighbors(Kinase):", sorted(G.neighbors("Kinase")))
print("out_neighbors(Kinase):", sorted(G.out_neighbors("Kinase")))
print("in_neighbors(Target):", sorted(G.in_neighbors("Target")))
print("successors(TF):", sorted(G.successors("TF")))
print("predecessors(Target):", sorted(G.predecessors("Target")))
print("neighbors(Kinase):", sorted(G.neighbors("Kinase")))
print("out_neighbors(Kinase):", sorted(G.out_neighbors("Kinase")))
print("in_neighbors(Target):", sorted(G.in_neighbors("Target")))
print("successors(TF):", sorted(G.successors("TF")))
print("predecessors(Target):", sorted(G.predecessors("Target")))
neighbors(Kinase): ['TF', 'Target'] out_neighbors(Kinase): ['TF', 'Target'] in_neighbors(Target): ['Kinase', 'Signal', 'TF'] successors(TF): ['Target'] predecessors(Target): ['Kinase', 'Signal', 'TF']
History¶
Mutating methods are wrapped automatically, so the history log is available without extra instrumentation.
In [4]:
Copied!
events = G.history()
len(events), events[-3:]
events = G.history()
len(events), events[-3:]
Out[4]:
(5,
[{'version': 3,
'ts_utc': '2026-03-30T11:23:47.862741Z',
'mono_ns': 5717556,
'op': 'add_hyperedge',
'members': None,
'head': ['Kinase', 'TF'],
'tail': ['Target'],
'slice': None,
'weight': 1.0,
'edge_id': 'he_program',
'edge_directed': None,
'attributes': {},
'result': 'he_program'},
{'version': 4,
'ts_utc': '2026-03-30T11:23:47.862775Z',
'mono_ns': 5749778,
'op': 'mark',
'label': 'initial_network'},
{'version': 5,
'ts_utc': '2026-03-30T11:23:47.862861Z',
'mono_ns': 5835862,
'op': 'add_edge',
'source': 'Target',
'target': 'Signal',
'slice': None,
'weight': 1.0,
'edge_id': 'feedback',
'as_entity': False,
'propagate': 'none',
'slice_weight': None,
'directed': None,
'edge_directed': False,
'attributes': {},
'result': 'feedback'}])
In [5]:
Copied!
G.history(as_df=True)
G.history(as_df=True)
Out[5]:
shape: (5, 20)
| version | ts_utc | mono_ns | op | source | target | slice | weight | edge_id | as_entity | propagate | slice_weight | directed | edge_directed | attributes | result | members | head | tail | label |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| i64 | str | i64 | str | str | str | null | f64 | str | bool | str | null | null | bool | struct[0] | str | null | list[str] | list[str] | str |
| 1 | "2026-03-30T11:23:47.862553Z" | 5536746 | "add_edge" | "Signal" | "Kinase" | null | 1.0 | "e_signal" | false | "none" | null | null | null | {} | "e_signal" | null | null | null | null |
| 2 | "2026-03-30T11:23:47.862655Z" | 5632007 | "add_edge" | "Kinase" | "TF" | null | 1.0 | "e_tf" | false | "none" | null | null | null | {} | "e_tf" | null | null | null | null |
| 3 | "2026-03-30T11:23:47.862741Z" | 5717556 | "add_hyperedge" | null | null | null | 1.0 | "he_program" | null | null | null | null | null | {} | "he_program" | null | ["Kinase", "TF"] | ["Target"] | null |
| 4 | "2026-03-30T11:23:47.862775Z" | 5749778 | "mark" | null | null | null | null | null | null | null | null | null | null | {} | null | null | null | null | "initial_network" |
| 5 | "2026-03-30T11:23:47.862861Z" | 5835862 | "add_edge" | "Target" | "Signal" | null | 1.0 | "feedback" | false | "none" | null | null | false | {} | "feedback" | null | null | null | null |
Use mark() when you want a named point in the event stream before a new block of operations.
In [ ]:
Copied!