Result¶
Result is the immutable snapshot returned by infomap.run() and
Infomap.run(). Scalar metrics are properties; node and tree collections
are methods with defaults (modules(level=1), nodes(), to_dataframe()).
- class infomap.Result(engine: Infomap, *, generation: int)¶
Immutable snapshot of an Infomap run.
Returned by
Infomap.run()(and the functionalinfomap.run()) and used to back the legacy on-instance accessors. Holds eager O(1) scalars; tree-derived metrics (theeffective_num_*modules) and node/tree/dataframe data are materialized lazily and guarded against the engine being re-run.Carries the result-artifact file writers (
write_tree,write_clu,write_flow_tree, …): write the mapequation.org tool files straight off the result, whatever built it. Like all node-level access, writing is generation-guarded — a staleResultraises instead of writing the rebuilt tree.Read scalars as properties and collections as methods (with defaults):
Examples
Run Infomap and read the partition off the
Result:>>> from infomap import Infomap >>> im = Infomap() >>> im.add_links(((1, 2), (1, 3), (2, 3), (4, 5), (4, 6), (5, 6), (3, 4))) >>> result = im.run() >>> result.num_top_modules 2 >>> for node_id, module_id in sorted(result.modules().items()): ... print(node_id, module_id) 1 1 2 1 3 1 4 2 5 2 6 2
Per-node views via
nodes()(a physical-node default; passstates=Truefor state nodes):>>> for node in sorted(result.nodes(), key=lambda n: n.node_id): ... print(node.node_id, node.module_id, f"{node.flow:.4f}") 1 1 0.1429 2 1 0.1429 3 1 0.2143 4 2 0.2143 5 2 0.1429 6 2 0.1429
A
Resultis a snapshot, not a live handle: re-running the sameInfomaprebuilds the C++ result tree, so node-level access on the oldResultraises. Eager scalars (codelength,num_top_modules, …) stay valid.For a sweep,
summary()returns the scalar metrics as a dict (one row per run, sopandas.DataFrame(r.summary() for r in results)builds a table) andto_series()gives the pandas-native row; both read only the eager scalars and stay valid after a re-run.- effective_num_modules(level: int | None = None, *, depth: int | None = None, depth_level: int | None = None) float¶
Return the flow-weighted effective number of modules at
level.Measured as the perplexity of the module flow distribution. Equivalent to the legacy
Infomap.get_effective_num_modules(depth_level).- Parameters:
level (int, optional) – The module level.
1(default) is the top (coarsest) level;-1the bottom (leaf-module) level.depth (int, optional) –
Deprecated since version 2.16: Alias of
level; leaves in 3.0.depth_level (int, optional) –
Deprecated since version 2.16: Alias of
level(the pre-redesign spelling); leaves in 3.0.
- leaf_modules() Iterator[InfomapLeafModuleIterator]¶
Iterate the leaf modules (bottom modules containing leaf nodes), depth first from the root.
Equivalent to the legacy
Infomap.leaf_modulesiterator.- Returns:
Yields each leaf module (the live
InfomapLeafModuleIteratorpositions). The iterator is generation-guarded: consuming it after the bound engine re-runs raises instead of walking a rebuilt tree.- Return type:
generator
- links(data: str = 'weight') Iterator[tuple[int, int, float]]¶
Iterate the partitioned links with their weight or flow.
Equivalent to the legacy
Infomap.get_links(data). The sources and targets are state ids for a state or multilayer network.- Parameters:
data (str, optional) – The kind of value to return, one of
"weight"or"flow". Default"weight".- Returns:
(source, target, weight_or_flow)tuples. The generator is generation-guarded liketree(): consuming it after the bound engine re-runs raises instead of reading the rebuilt engine.- Return type:
- modules(level: int | None = None, *, states: bool = False, depth: int | None = None, depth_level: int | None = None) dict[int, int]¶
Map
node_id(orstate_idwhenstates) tomodule_id.Equivalent to the legacy
Infomap.get_modules(depth_level, states): for a higher-order (multilayer/memory) network, requesting physical-node modules withoutstatesis ambiguous and raises, mirroring the C++getModulesguard.- Parameters:
level (int, optional) – The level in the hierarchical tree of the reported module ids.
1(default) is the top (coarsest) level;-1the bottom (finest) level.states (bool, optional) – Key the mapping by
state_idwhenTrue, bynode_idwhenFalse(the default).depth (int, optional) –
Deprecated since version 2.16: Alias of
level; leaves in 3.0. (TreeNode.depthis a node’s distance from the root, a different quantity.)depth_level (int, optional) –
Deprecated since version 2.16: Alias of
level(the pre-redesign spelling); leaves in 3.0.
- Returns:
{node_or_state_id: module_id}for every leaf node.- Return type:
dict of int to int
- Raises:
InfomapError – For a higher-order network when
statesisFalse.
See also
multilevel_modulesModule ids for every level at once.
treeWalk the full hierarchical tree.
- multilevel_modules(*, states: bool = False) dict[int, tuple[int, ...]]¶
Map each node to its module on every level, from the top down.
Read the tuples column by column: the first entries give the partition at the top level, the second entries the partition one level down, and so on. Module ids are numbered per level, so the same id can mean different modules on different levels.
For example, this tree has a top module 2 with no submodules:
root ├── 1 │ ├── 1:1 nodes a, b │ └── 1:2 nodes c, d └── 2 nodes e, f
and gives:
{a: (1, 1), b: (1, 1), c: (1, 2), d: (1, 2), e: (2, 3), f: (2, 3)}
The top level is {a, b, c, d} and {e, f}; the level below is {a, b}, {c, d} and {e, f}.
Equivalent to the legacy
Infomap.get_multilevel_modules(states).Notes
The tuples are not tree paths. All tuples have the same length, so a module without submodules appears again on each lower level, under that level’s id:
egets(2, 3)although its tree path is(2,). For tree paths, readnode.pathfromnodes().
- nodes(level: int | None = None, *, states: bool = False, depth: int | None = None, depth_level: int | None = None) Iterator[TreeNode]¶
Iterate leaf
TreeNodeviews, depth first from the root.- Parameters:
level (int, optional) – The module level reported by
node.module_id.1(default) is the top (coarsest) level;-1the bottom (finest).states (bool, optional) – Iterate state nodes when
True. WhenFalse(the default), iterate physical nodes, merging state nodes with the samenode_idif they are in the same module; the same physical node may then appear on different paths in the tree.depth (int, optional) –
Deprecated since version 2.16: Alias of
level; leaves in 3.0. Not the yieldednode.depth, which is the node’s distance from the root.depth_level (int, optional) –
Deprecated since version 2.16: Alias of
level(the pre-redesign spelling); leaves in 3.0.
- Returns:
An immutable snapshot view per leaf node. Materialized when the first node is pulled, so an iterator acquired before the bound engine re-runs raises the stale-result error on iteration, as
tree()does.- Return type:
iterator of TreeNode
- provenance() dict[str, Any]¶
What a reader needs to reproduce this run, as a plain
dict.The engine’s own record of the run, read programmatically – so a run can be logged from a running program without a manifest-file round trip (#1026). The published artifacts carry parts of it: the
.tree/.ftree/.cluheaders and the JSON tree stamp the fingerprints (and the input size), but only--manifest-jsonand this method carry the canonical config and the input paths. Keys:version: the engine version, e.g."v2.16.0".args: the raw argument string the engine was configured with.seed: the effective base seed (the default when none was given),trialOffset, andtrialsofnumTrials.config: the canonical configuration the run used, one entry per algorithm-affecting option, andconfigFingerprint, its hash – the same fingerprint--print-config-fingerprintprints.input,clusterData,metaData:{path, size, mtime, hash}for each file the run read, wherehashcovers the whole content, orNonewhen no file is known – a network built in memory has no input identity, and an option not used has none.
Returns a copy; mutating it does not affect the
Result.Added in version 2.16.
Examples
>>> import infomap >>> result = infomap.run([(1, 2), (2, 3), (3, 1)], seed=7) >>> record = result.provenance() >>> record["seed"], len(record["configFingerprint"]) (7, 16) >>> record["input"] is None # built in memory, so no file to identify True
- summary() dict[str, Any]¶
Return the result’s scalar metrics as a plain
dict.A one-row-per-run record for collecting a sweep into a table: write the loop as you normally would and drop each summary into pandas, adding your own swept-parameter columns alongside:
records = [] for markov_time in (0.5, 1.0, 2.0): result = infomap.run(graph, markov_time=markov_time, seed=123) records.append({"markov_time": markov_time, **result.summary()}) df = pandas.DataFrame(records)
The keys match the scalar
Resultproperty names, so each column reads the same as the attribute you would read off a single result (df["codelength"]mirrorsresult.codelength).This is distinct from
Infomap.summary(). That method describes the stateful instance – network counts and runstatus, available even before a run – and keys its module counts with the shorter card names (top_modules,levels).Result.summaryreports only a finished run’s result metrics, keyed by theResultproperty names (num_top_modules,num_levels); it is the shape to collect into a sweep table.A curated set of the eagerly captured O(1) scalars is included, so
summaryis cheap and stays valid for the life of theResult: it never walks the tree and never raisesStaleResultError, even after the bound engine has re-run. The tree-derivedeffective_num_*metrics and the per-trialcodelengthsare intentionally left out (read them off their properties when needed). A few eager scalars are also omitted to keep the row focused on the common case – add them yourself when a sweep needs them:meta_codelength/meta_entropy(metadata runs),num_physical_nodesandhave_memory(higher-order networks).- Returns:
{metric_name: value}for the scalar result metrics.- Return type:
See also
to_seriesthe same record as a
pandas.Series.to_dataframethe per-node table for a single result.
Infomap.summarythe stateful instance’s state card (different keys).
Examples
>>> import infomap >>> result = infomap.run(infomap.datasets.two_triangles(), seed=123) >>> summary = result.summary() >>> summary["num_top_modules"] 2 >>> summary["codelength"] == result.codelength True >>> "num_levels" in summary True
- to_dataframe(columns: Sequence[str] | None = None, *, states: bool = False, level: int | None = None, index: str | bool | None = None, sort: bool | str | Sequence[str] = False, depth: int | None = None, depth_level: int | None = None) pandas.DataFrame¶
Return a pandas DataFrame of the leaf nodes.
Byte-identical to the legacy
Infomap.to_dataframe.- Parameters:
columns (sequence of str, optional) – Columns to include.
"community"is accepted as an alias for"module_id"."name"resolves the physical node name (falling back to the integernode_id); the opt-in"state_name"resolves the per-state-node name for a higher-order network (falling back to the physical name, thennode_id); seestate_names. Default["node_id", "module_id", "flow", "path", "name"].states (bool, optional) – Use state nodes when
Trueand physical nodes whenFalse(the default).level (int, optional) – The module level reported by
module_id, as inmodules().1(default) is the top (coarsest) level;-1the bottom (finest).index (str, bool, or None, optional) – Column to set as the DataFrame index. Use
FalseorNone(the default) to keep the default RangeIndex.sort (bool, str, or sequence of str, optional) – Sort by one or more columns. Use
Trueto sort by["module_id", "node_id"]when available. DefaultFalse.depth (int, optional) –
Deprecated since version 2.16: Alias of
level; leaves in 3.0. (The"depth"column is a node’s distance from the root, a different quantity.)depth_level (int, optional) –
Deprecated since version 2.15: Alias of
level; leaves in 3.0.
- Returns:
One row per leaf node, with the requested columns.
- Return type:
- Raises:
ImportError – If pandas is not installed.
ValueError – If an unknown column is requested, or if
leveland one of its aliases are given conflicting values.
- to_igraph(*, module_attribute: str | None = 'infomap_module', path_attribute: str | None = 'infomap_path', include_hierarchy: bool = True, flow_attribute: str | None = 'flow') igraph.Graph¶
Build a python-igraph graph of the partitioned network.
Equivalent to
infomap.to_igraph(); see it for the parameters and the attribute scheme.- Returns:
Directed when the partitioned network is directed, else undirected.
- Return type:
igraph.Graph
- to_networkx(*, module_attribute: str | None = 'infomap_module', path_attribute: str | None = 'infomap_path', include_hierarchy: bool = True, flow_attribute: str | None = 'flow') networkx.Graph¶
Build a NetworkX graph of the partitioned network.
Equivalent to
infomap.to_networkx(); see it for the parameters and the attribute scheme.- Returns:
DiGraphwhen the partitioned network is directed, elseGraph.- Return type:
- to_series() pandas.Series¶
Return the result’s scalar metrics as a
pandas.Series.The pandas-native form of
summary(): a one-row record indexed by metric name, so a sweep collects into one row per run withpandas.DataFrame([result.to_series() for result in results])
Like
summary(), this reads only the eager scalars, so it stays valid after the bound engine re-runs.- Returns:
The
summary()mapping as a Series indexed by metric name.- Return type:
- Raises:
ImportError – If pandas is not installed. Install it with
python -m pip install "infomap[pandas]".
See also
summarythe same record as a plain
dict.to_dataframethe per-node table for a single result.
- tree(level: int | None = None, *, states: bool = False, depth: int | None = None, depth_level: int | None = None) Iterator[InfomapIterator | InfomapIteratorPhysical]¶
Iterate the hierarchical tree, modules and leaf nodes alike, depth first from the root.
Equivalent to the legacy
Infomap.get_tree(depth_level, states). For a higher-order (multilayer/memory) network the physical tree is used unlessstatesis requested, mirroring the legacy semantics.- Parameters:
level (int, optional) – The module level reported by
iterator.module_id.1(default) is the top (coarsest) level;-1the bottom (finest).states (bool, optional) – Iterate over state nodes when
True, physical nodes whenFalse(the default).depth (int, optional) –
Deprecated since version 2.16: Alias of
level; leaves in 3.0.depth_level (int, optional) –
Deprecated since version 2.16: Alias of
level(the pre-redesign spelling); leaves in 3.0.
- Returns:
Yields each node in the tree (the live
InfomapIterator/InfomapIteratorPhysicalpositions), depth first from the root. The iterator is generation-guarded: consuming it after the bound engine re-runs raises instead of walking a rebuilt C++ tree.- Return type:
generator
- write(filename: str | PathLike[str], *args, **kwargs) None¶
Write results to file, inferring the format from the extension.
An existing file at
filenameis overwritten.- Raises:
ValueError – If
filenamehas no extension to infer the format from.NotImplementedError – If the file format is not supported on this host.
- Parameters:
filename (str or os.PathLike) – The filename.
- write_clu(filename: str | PathLike[str], states: bool = False, level: int | None = None, *, depth: int | None = None, depth_level: int | None = None) None¶
Write result to a clu file.
An existing file at
filenameis overwritten.See also
- Parameters:
filename (str or os.PathLike)
states (bool, optional) – If the state nodes should be included. Default
False.level (int, optional) – The level in the hierarchical tree to write. Accepted positionally, matching
result.modules(level=...)andresult.to_dataframe(level=...).1(default) is the top level,-1the bottom.depth (int, optional) –
Deprecated since version 2.16: Alias of
level; leaves in 3.0.depth_level (int, optional) –
Deprecated since version 2.15: Alias of
level(the historicalwrite_clukeyword); leaves in 3.0.
- write_csv(filename: str | PathLike[str], states: bool = False) None¶
Write result to a CSV file.
An existing file at
filenameis overwritten.See also
- Parameters:
filename (str or os.PathLike)
states (bool, optional) – If the state nodes should be included. Default
False.
- write_flow_tree(filename: str | PathLike[str], states: bool = False) None¶
Write result to a ftree file.
An existing file at
filenameis overwritten.See also
- Parameters:
filename (str or os.PathLike)
states (bool, optional) – If the state nodes should be included. Default
False.
- write_json(filename: str | PathLike[str], states: bool = False) None¶
Write result to a JSON file.
An existing file at
filenameis overwritten.See also
- Parameters:
filename (str or os.PathLike)
states (bool, optional) – If the state nodes should be included. Default
False.
- write_newick(filename: str | PathLike[str], states: bool = False) None¶
Write result to a Newick file.
An existing file at
filenameis overwritten.See also
- Parameters:
filename (str or os.PathLike)
states (bool, optional) – If the state nodes should be included. Default
False.
- write_tree(filename: str | PathLike[str], states: bool = False) None¶
Write result to a tree file.
An existing file at
filenameis overwritten.See also
- Parameters:
filename (str or os.PathLike)
states (bool, optional) – If the state nodes should be included. Default
False.
- property effective_num_leaf_modules: float¶
The flow-weighted effective number of leaf modules.
Measured as the perplexity of the leaf-module flow distribution. Unlike the eager scalar properties, this is computed lazily on first access (see
effective_num_modules()), so it can raiseStaleResultErrorif the bound engine has re-run since.
- property effective_num_top_modules: float¶
The flow-weighted effective number of top modules.
Measured as the perplexity of the top-module flow distribution. Unlike the eager scalar properties, this is computed lazily on first access (see
effective_num_modules()), so it can raiseStaleResultErrorif the bound engine has re-run since.
- property flow_converged: bool¶
Whether the flow calculation’s power iteration reached its tolerance.
Falsemeans the iteration’s final error stayed aboveflow_tolerance, so the flow is not the network’s stationary distribution and every codelength derived from it describes something else. Reaching tolerance on the last allowed iteration counts as converged; running out of iterations with the error still too large does not. The run still completes and writes output, so this is the only way an automated consumer can tell (flow_errorsays by how much).Truefor flow models that run no power iteration at all – undirected flow, for instance – sonot result.flow_convergedalways means a real failure.flow_iterationsis 0 in that case.Examples
>>> from infomap import Infomap, Options >>> im = Infomap(silent=True) >>> im.read_file("ninetriangles.net") >>> result = im.run(options=Options(directed=True, max_flow_iterations=2)) >>> result.flow_converged False >>> result.flow_iterations 2
- property flow_error: float¶
The power iteration’s final error, 0.0 if it ran none.
Compare against the
flow_toleranceoption: an error above it withflow_convergedfalse says how far the flow is from stationary.
- property max_depth: int¶
Alias of
num_levels.Deprecated since version 2.16: Use
num_levels; the tree is described in levels, anddepthis a node’s distance from the root (TreeNode.depth).
- property names: dict[int, str]¶
All node names, as
{node_id: name}.Maps each internal
node_idto the label of the input node. It is populated only when the input labels are not already the integer ids – for a graph whose nodes are integers (contiguous or not) the ids are the labels, so this is empty andmodules()is keyed by those integers directly. Theresult.names.get(nid, nid)idiom therefore recovers labels for both cases. Returns a copy; mutating it does not affect theResult.
- property num_levels: int¶
The number of levels in the hierarchical tree, leaves included.
A two-level result has one module level above the leaves. The module levels a reader selects are
level=1(top) throughlevel=num_levels - 1(finest), orlevel=-1for the finest.On a ragged tree, where some branches end earlier than others, this is the depth of the deepest leaf – the same number the console summary, the
.treeheader and the JSON output report.Changed in version 2.16: Counts the deepest branch. It used to follow one arbitrary branch, so a ragged tree could report fewer levels here than in the engine’s own output.
- property num_non_trivial_top_modules: int¶
The number of non-trivial top modules (size not 1 or all).
- property num_physical_nodes: int¶
The number of physical nodes.
Equals
num_nodesfor a first-order network; for a higher-order (multilayer/memory) network it counts the distinct physical nodes behind the state nodes. Captured eagerly, so it stays valid after a re-run.
- property state_names: dict[int, str]¶
All state-node names, as
{state_id: name}.Returns a copy; mutating it does not affect the
Result.Populated for higher-order (state/memory) networks whose
*Statessection names the state nodes; empty otherwise. Physical node names are available separately vianames.
TreeNode is the lightweight, immutable per-node view yielded by
Result.nodes().
- class infomap.TreeNode(*, node_id: int, state_id: int, module_id: int, flow: float, depth: int, layer_id: int, child_index: int, modular_centrality: float, path: tuple[int, ...], name: str | int, state_name: str | int)¶
A lightweight, immutable view over a single leaf node of a
Result.Yielded by
Result.nodes(). A plain Python object: attribute access reads from the snapshot data theResultalready materialized, without touching the underlying C++ engine, so it stays valid after a re-run.- depth¶
The depth of the node in the tree (number of levels below the root; equals
len(path)).- Type:
- path¶
The tree path from the root as a tuple of one-based child indices (the colon-separated path in tree output files).