cograph 2.4.4
New features
-
Producer-supplied splot metadata (
x$meta$splot): packages that create cograph-plottable objects can now attach a small rendering contract —renderer(resolved through a cograph-maintained whitelist of existing renderers; arbitrary function names are never evaluated),weight(which stored edge quantity to render: an edge column keeps the producer’s edge set, a matrix redefines the drawn network from its nonzero cells, aligned by dimnames), anddefaults(renderer arguments). Precedence is alwaysuser arguments > meta$splot$defaults > cograph defaults; on the regular network path this includes deprecated argument aliases (a user-suppliedpositive_colorstill beats a metadataedge_positive_colordefault). See?splot, section “Producer-Supplied splot Metadata”.
Bug fixes / changes
plot_bootstrap_forest(),extract_motifs(),motif_census(),triad_census()andextract_triads()are now listed in the package index and the reference site. All five are exported and user-facing, but carried@keywords internal, which hid them fromhelp(package = "cograph")— you could only find them if you already knew the name.mcml()remains hidden; it is a deprecated alias ofcsum(). Thenand...arguments ofprint.cograph_motif_analysis()andprint.cograph_motifs()are now documented (previously exempt from checking by theinternalkeyword).plot_difference()’s newdifferenceargument moved to the end of the signature, aftercombined. It had been inserted beforecombined, which shifted the positional argument order relative to the released 2.3.6 signature. Becauseplot_compare()isfunction(x, ...)and forwards toplot_difference(), a caller passing 14 positional arguments had their 14th silently rebound fromcombinedtodifference— making the function treatxas an already-subtracted matrix, discardy, and draw the wrong network with no error.differencewas introduced after the last CRAN release, so no released behaviour changes. Named calls were never affected.plot_bootstrap_forest()andplot_edge_diff_forest()no longer emit ageom_errorbarh()deprecation warning under ggplot2 4.0.0. The four horizontal error-bar layers now usegeom_errorbar(orientation = "y"); the rendered output is unchanged.DESCRIPTIONnow declares theggplot2 (>= 3.4.0)requirement the package already had (it uses thelinewidthaesthetic throughout).plot_edge_diff_forest(layout = "chord")no longer emits a spurious “row names were found from a short variable and have been discarded” warning for every node arc it draws.aggregate_layers(),supra_adjacency(),layer_similarity_matrix()andplot_motifs()now ship runnable examples. Their\examplessections were previously commented out (or entirely\dontrun), so they demonstrated nothing and were never checked. The remaining\dontrunblocks inmotifs()andextract_motifs()are now\donttest, so they are executed underR CMD check --run-donttest.detect_communities()with the"louvain"(the default) or"leiden"method no longer errors on a directed graph. These igraph algorithms are undirected-only, sodetect_communities(tna_object)— a tna model is always directed — aborted with “Multi-level community detection works for undirected graphs only”. It now collapses the directed edges to undirected (mean, as the"fast_greedy"method already did) with a message, so the package’s primary object type works with the default algorithm. This also fixesplot_htna(x, community = "louvain")and other internal callers that ran community detection on a directed model.splot()on a Nestimatenetdifference(fromsubtract_networks()/as_netdifference()) now routes toplot_difference(). Previously it fell through to thenetobjectpath, which styles by$method— “difference” is not a TNA-family method, so the asymmetric difference matrix was drawn with undirected psych styling: no arrowheads and one triangle of each asymmetric edge pair silently dropped.splot(d, minimum = 3)is now the straightforward call for a signed difference network.The
netdifferencerouting excludesnet_permutation-family objects:net_bayescarries both classes and must keep reachingsplot.net_permutation, whose per-edge CI/star arrays are aligned byNestimate::plot.net_bayesto that renderer’s edge ordering.plot_difference()on anetdifferencenow draws the display matrix ($weights— e.g. only the credible differences when coerced withas_netdifference(b, significant_only = TRUE)), falling back to$difference_matrix. Forsubtract_networks()results the two are identical, so nothing changes there.plot_permutation()/splot.net_permutation(): thetitleandlayoutdefaults now use exact[[indexing.args$titleon a dots-list holdingtitle_size(but notitle) partially matchedtitle_size, so the default title was silently skipped and no title was drawn — this is whyNestimate::plot.net_bayes()output had no title. Same latent hazard fixed forlayout/layout_scale.Edge label templates gain a
{p_diff}placeholder (probability of the difference, for Bayesian comparisons), fed by the newedge_label_p_diffargument — a per-edge vector or a full node-by-node matrix (the matrix is indexed at each drawn edge, so it survivesminimum/thresholdfiltering, and is aligned by dimnames so it may be supplied in any node order). Filled automatically from$p_differencebysplot.net_permutationand byplot_difference()on Bayesiannetdifferencecoercions. Template example:edge_label_template = "{est} (P={p_diff})".splot.netobject()styling classifier:"edge_betweenness"networks are now styled by their directedness. A directed edge-betweenness network previously fell into psych styling — drawn undirected, silently losing one direction of each asymmetric pair; it now gets the TNA presets with arrows. An undirected one (from a correlation-family source — Nestimate preserves the source’s directedness) keeps the psych look.Nestimate producers now use the
meta$splotcontract:netdifferenceobjects carryrenderer = "difference"andnet_bayescarriesrenderer = "permutation", so metadata routing (which runs before class dispatch) selects the renderer; thenetdifferenceclass branch remains as a fallback for objects built without metadata.
cograph 2.4.3
Bug fixes / changes
plot_difference()no longer hides small difference edges: it defaultsminimum = 0(the style presets otherwise injectedminimum = 0.01, silently dropping edges with|x - y| < 0.01). An explicitminimumstill wins.plot_difference(x, y, difference = TRUE)now warns thatyis ignored and usesxas the difference network, instead of silently computingx - y.
cograph 2.4.2
Bug fixes / changes
plot_compare()is no longer deprecated — it is a plain alias ofplot_difference().tna::plot_compare()delegates to it by name (cograph::plot_compare(x, y, ...)), so deprecating it wrongly made everytna::plot_compare()call emit a warning; the warning is removed. Both names call the same implementation;plot_difference()is the preferred spelling for new cograph code.plot_difference()also auto-detects a Nestimatenetdifferenceobject (or any object exposing$difference_matrix), alongsidetna_comparison.
cograph 2.4.1
New features
-
plot_difference()can now consume a pre-computed difference network: atna_comparisonobject (fromtna::compare()) is detected automatically and its$difference_matrixis plotted, anddifference = TRUEtreatsxas an already-subtracted matrix/network (noyneeded). The two-networkplot_difference(x, y)path is unchanged.
cograph 2.4.0
New features
- Two focal-node flow layouts, usable anywhere a layout name is accepted (
splot(x, layout = "target")/layout = "saqr"):-
layout_target()ports qgraph’sflow()— places one node of interest (target =) on the left and every other node in columns by unweighted BFS distance (hops). Unlike qgraph it handles disconnected graphs (isolated nodes go to a trailing column) instead of erroring. -
layout_saqr()ports the Dynalytics Desktop “saqr” transition layout (Saqr et al., LAK25): Start on top, End on bottom, middle nodes ranked by outgoing weight from Start and split into 2–3 sine-enveloped rows with a zig-zag first row (start =,end =,jitter =).
-
Bug fixes / changes
plot_difference()now styles the difference network automatically instead of drawing bare default-blue nodes: an undirected difference gets the psychometric look (Okabe-Ito node palette, no arrows, thin edges), a directed difference gets the TNA look (TNA palette, arrows). Node size uses the calibrated preset (previously nodes could render near-invisible), and edges stay coloured by the sign of the difference. Explicitnode_*arguments still override the preset.plot_difference()is added as the preferred name for the difference-network plotter.plot_compare()remains a first-class alias of it (tna::plot_compare()delegates tocograph::plot_compare()by name, so the name must keep working).plot_difference()(the renamed difference-network plotter) now treats an S3cograph_network(which is itself a list — e.g. apsychnetfit, a Nestimatenetobject, or anyas_cograph()result) as a single network. Previously such an object fell into the “plain list of networks” branch and was misread as a list of sub-networks, failing with “x must be a matrix, cograph_network, tna, or igraph object”. Comparing two psychnet/netobject networks withplot_difference(net1, net2)now works.
cograph 2.3.11
New features
dyad_census()classifies every dyad of a directed network into mutual (M), asymmetric (A), or null (N), returning a tidy one-row-per-type data.frame with counts and proportions and a dyad-based reciprocity (2M / (2M + A)) attribute. It is the dyad-level companion totriad_census(). Undirected input counts every edge as a mutual dyad.ego_networks()reports tidy per-ego personal-network metrics — size, ego/alter tie counts and densities, and Burt’s structural-hole measures (effective_size,constraint,order = 1only) — with one row per ego. The structural-hole columns reuse the same implementations ascentrality(), so they matchcentrality(x, measures = c("effective_size", "constraint"))exactly.
cograph 2.3.10
Bug fixes / changes
Bootstrap plots of undirected co-occurrence networks (
splot.net_bootstrap) now default to the"oval"layout instead of the force-directed"spring"layout, matchingsplot.tna_bootstrap. Passlayout = "spring"to restore the previous behavior.Bootstrap plots now auto-suppress the
".00"decimal tail on integer-valued weight matrices (co-occurrence counts, raw frequencies):266.00**renders as266**. Detection mirrorssplot.netobject— when every nonzero weight is a whole number and the user has not setweight_digits, bothweight_digitsandedge_label_digitsdefault to0. Applies to bothsplot.net_bootstrapandsplot.tna_bootstrap. Non-integer (correlation/GLASSO) networks are unaffected, and an explicitweight_digitsalways wins.
cograph 2.3.9
New features
plot_mcml()gains athemeargument:"classic"(default — the established pie-node / straight-edge look, now with thinner node and shell borders and slightly larger detail nodes),"rich"(donut nodes on both layers plus curved summary edges and splot self-loops), and"light"("rich"with no shell outline and a softer fill). Granular overridesnode_donut,node_donut_inner_ratio,summary_donut_inner_ratio,summary_donut_show_value,curved_edges, andsummary_curvewin over the preset.plot_mcml()now colors edges by weight sign on every layer (within-cluster, between-cluster, summary, and self-loops) viaedge_color_by:"auto"(default) keeps cluster coloring for non-negative transition networks but switches to sign coloring when any negative weight is present (correlation / association networks),"cluster"and"sign"force either mode. Positive edges useedge_positive_color("#2E7D32", green) and negative edgesedge_negative_color("#C62828", red), matchingsplot(). Edge visibility thresholding and width scaling now use the absolute weight, so negative edges are drawn rather than silently dropped, and a positive/negative key is added to the legend when sign coloring is active.plot_mcml()summary-node labels are now placed “on the clock”: each label sits just outside its node in the cardinal direction the node points from the arrangement center (top at 12, bottom at 6, left at 9, right at 3), anchored at the node boundary so it always clears the node regardless ofsummary_size. An explicitsummary_label_positionstill overrides this.
cograph 2.3.8
New features
-
plot_mcml()andsplot()acceptmcml_pcobjects (Nestimate::build_mcml_pc(), experimental psychometric MCML) and render them undirected via theirmeta$directedflag.
cograph 2.3.7
Breaking changes
- The exported names
cluster_summary()andbuild_mcml()are removed to end, permanently, the collision withNestimate::cluster_summary()andNestimate::build_mcml()— different functions that silently masked each other depending on package attach order (the same disease as thecluster_network()alias removed in 2.3.6, where load order silently flipped results between raw counts and row-normalized probabilities). Migration is name-for-name with identical behavior:-
cluster_summary(...)→csum(...)(the existing short alias is now the canonical exported name; same arguments, samecluster_summaryreturn object). -
build_mcml(...)→summarize_clusters(...)(same arguments, samemcmlreturn object). In sessions where both packages are attached, the bare namescluster_summary()/build_mcml()now always refer to Nestimate’s data-layer verbs, regardless of attach order. Theas_tna()generic is intentionally exported by both packages: the definitions are identical (function(x) UseMethod("as_tna")), so masking is harmless and S3 methods from both packages dispatch correctly.
-
New features
-
plot_mcml()gains adirectedargument (defaultNULL= auto-detect). Undirected rendering suppresses arrowheads on all three edge layers (within-cluster, between-cluster, summary), draws each symmetric edge pair once instead of twice (previously a symmetric matrix produced overplotted reciprocal arrows), and moves edge labels to the edge midpoint. Auto-detection reads$meta$directedfromcluster_summary/mcmlinput (e.g., co-occurrence aggregations such asNestimate::build_mcml(type = "cooccurrence")now render undirected with no extra flag), the$directedfield of network objects, or matrix symmetry for plain matrices — the same contract assplot(), which forwardsdirectedwhen dispatchingmcml/cluster_summaryobjects. -
plot_mcml()undirected matrix input is aggregated withcluster_summary(type = "cooccurrence")(symmetrized counts) instead of the row-normalizedtype = "tna", whose output is asymmetric even for symmetric input and cannot be represented by undirected drawing. Whendirected = FALSEis forced on weights that are not symmetric,plot_mcml()now warns that only the upper triangle is drawn.
Bug fixes
-
cluster_summary()and the sequence path ofbuild_mcml()now record the effective directedness in$meta$directed:FALSEwhentype = "cooccurrence"(which symmetrizes the weights), instead of echoing thedirectedargument unchanged.
cograph 2.3.6
CRAN release: 2026-05-31
Bug fixes
- Removed the
cluster_network()alias forsummarize_network(). It collided withNestimate::cluster_network()— a completely different function (PAM clustering on sequence data, one network per cluster) — and the two silently masked each other depending on package attach order, producing confusingunused arguments (k = ..., cluster_by = ...)errors. Usesummarize_network()(or its remaining short formcnet()) for matrix-to-cluster aggregation in cograph.
cograph 2.3.4
Bug fixes
-
.smooth_blob()(used byplot_simplicial()andoverlay_communities()) now guardsgrDevices::chull()against non-finite anchor coordinates. Previously a node lacking layout coordinates (NA/Inf) aborted the blob with “finite coordinates are needed”; such anchors are now dropped before the convex-hull step.
cograph 2.3.3
Documentation
- Aligned the
motifs()/subgraphs()roxygen documentation with the post-audit behavior shipped in 2.3.2 (censustype_summarycounts,min_counthandling, and corrected plot legend descriptions).
cograph 2.3.2
Bug fixes
- Full audit pass over the motifs subsystem:
type_summarynow holds real MAN-type counts in census mode,min_countis honored in census mode, and the swapped source/target color description inplot.cograph_motif_result()is corrected. - Unbroke
motifs()andplot_simplicial()on Nestimate-backed workflows (HON / HYPA sequence inputs). -
panel_layout(): tightened dimension validation and made the restoration claim honest — it now restores only thepar()settings it actually changed.
cograph 2.3.1
Multi-panel layout control
- New
combinedargument (defaultTRUE) on every multi-panel plot function:splot()group-cascade,plot_netobject_group(),plot_netobject_ml(),plot_net_bootstrap_group(),plot_group_permutation(),plot_compare(),splot.net_mlvar(),plot_network_evolution(),plot.cograph_motifs(),plot.cograph_motif_result(),plot.cograph_motif_analysis(), andplot.tna_disparity(). Withcombined = FALSEthese functions draw panels into the active device without callinggraphics::par(mfrow=...), so callers can drive their own layout (e.g.graphics::layout()or the newpanel_layout()helper). DefaultTRUEpreserves prior behavior — every existing call site renders identically. - New
panel_layout()helper sets up a custom multi-panel device layout for use withcombined = FALSE. Accepts either a uniform-gridc(nrow, ncol)or agraphics::layout()matrix for non-uniform layouts (e.g. one wide panel + two narrow ones). Returns apar()snapshot for restoration viaon.exit().
Test suite hygiene
-
test-coverage-splot-{41,42}.R: bumpedn_nodesfrom 4 to 10 in seven per-edge attribute tests so the seed=42 sampler does not produce duplicate (1,2) pairs that trip cograph’s undirected-duplicate-edge detector. -
test-coverage-class-network-41.R: aligned theset_layout_coords()mismatched-row-count test with the strict input validation already enforced byR/class-network.R. -
test-overlay-communities.R: prefixed twocommunities()calls withcograph::to avoidtnamasking when both packages are loaded in the suite (per CLAUDE.md “namespace masking” gotcha).
cograph 2.3.0
Documentation
- Audited every R/*.R function file for roxygen/Rd accuracy. Corrected stale defaults (
cr_color#D4820A->#D4829Ainplot-forest.R;show_valuedefaultFALSE->TRUEinsplot-nodes.R), corrected dataset dimensions indata-hai.R(302->429 x 287), corrected a reference to the nonexistentigraph::is_bipartite()(nowbipartite_mapping()), expandedcentrality()@parammeasure lists formode,cutoff,invert_weights, andmembershipto match the implementation, dropped baked-in measure counts that rot on each addition, and removed nonexistent themes fromsn_themedocumentation. No runtime behavior changes from the documentation pass itself.
Bug fixes
-
plot_simplicial()now warns whenanomalyis set on an input that has no anomaly concept (HON, association rules, link prediction, character pathways,method = "hon"/"rules"). Previously the argument was silently dropped, so calls likeplot_simplicial(hon, anomaly = "over")andplot_simplicial(hon, anomaly = "under")produced byte-identical plots.anomalyis honored only fornet_hypainputs andmethod = "hypa"auto-builds.
Centrality
-
centrality()gains an umbrella argumenttna_network(logical or NULL). WhenTRUE(or auto-detected from atna/group_tna/ctna/ftna/atnainput), all measures shared withtna::centralities()match byte-for-byte:loops = FALSE,invert_weights = TRUE,diffusion_method = "power_series",transitivity_type = "onnela". Side-by-side audit confirms zero divergence onOutStrength,InStrength,ClosenessIn/Out/All,Betweenness,Diffusion,Clustering(max|diff| = 0). Any per-argument override the user passes explicitly always wins over the umbrella. -
centrality()(andcentrality_diffusion()) gain adiffusion_method = c("kandhway_kuri", "power_series")argument. The defaultNULLauto-detects:"power_series"for tna inputs (matchestna::centralities(., measures = "Diffusion")byte-for-byte whenloops = FALSE),"kandhway_kuri"(the existing 1-hop binary-degree formula, Kandhway & Kuri 2014) for everything else. Previously cograph’s diffusion silently disagreed with tna’s because cograph used an unweighted neighborhood-degree sum while tna usesrowSums(P + P^2 + ... + P^n)on the diagonal-zeroed weighted matrix — the same name covered two different statistics. Set explicitly to override the auto-detect.
Tests
- Added a regression test in
tests/testthat/test-validate-nestimate-bootstrap-permutation.Rasserting thatcentrality()on a Nestimatenetobjectagrees withcentrality()on its$weightsmatrix when the diagonal is non-zero. Locks in the upstream Nestimate fix to.extract_edges_from_matrix()(Nestimate >= 2026-05-02) which now preserves self-loops in$edges. Without that fix, loop-bearing netobjects (e.g.Nestimate::build_mcml() |> Nestimate::as_tna()) silently under-counted node degree by 2.
Plotting — edge-label cex coupling (Phase 2)
- Default
edge_label_sizeis now coupled to the node label cex at a fixed 0.55 fraction (edge_cex = 0.55 * mean(node_label_cex)) so the node-to-edge-label ratio stays a stable ~1.82x across canvases. This replaces the previousEDGE_LABEL_SCALE_CAP-based compensation, which let the ratio drift from 2.5x at reference to 3.6x at poster canvases because edge labels were clamped to a tighter 1.6 ceiling while node labels scaled freely to 2.3. The visible effect: edge weight annotations are now readable at poster sizes instead of shrinking relative to node labels. User-explicitedge_label_sizestill wins and receives the same (capped) visual-scale compensation as before; only the default path changed. - Edge-label visual_scale resolution moved from
render_edges_splot()intosplot.Rso the final cex is produced in a single place.
Plotting — device-aware visual scaling
-
splot()now applies device-dependent compensation to text, line, and point sizes so visual ratios (label-to-node, legend-to-plot, edge thickness) stay consistent when the output device changes. This fixes the long-standing “labels too big at high DPI” and “legend desynchronised from the plot” issues when saving PNGs atres = 300orres = 600with pixel-defaultwidth/height, and when resizing the RStudio plot pane. Implementation: a singlecompute_visual_scale()reads the active device’s canvas size (dev.size("in")) and returns multipliers keyed off a 5.9-inch reference (matching the default RStudio 7×5” pane so backward-compatible behaviour at the default canvas is preserved). Multipliers are clamped to[0.55, 1.9]to keep thumbnails and posters legible. See the newR/visual-scale.R. - New
scaling = "fixed"mode onsplot()— and corresponding global optionoptions(cograph.visual_scaling = FALSE)— disables device compensation for reproducibility-sensitive workflows that calibrated against the previous behaviour. -
splot()return value now carries two attributes for downstream tooling:cograph.visual_scale(the multiplier list) andcograph.node_diam_in(the representative node diameter in inches at the rendered device). - The splot-internal
render_legend_splot()plus the new shared.render_legend_base()(R/render-legend-shared.R) replace the ad-hoc legend cex/pt.cex handling with a single compensated path.plot_htna,plot_mtna,plot_mlna,plot_mcmlstill use their historical scale multiplier arguments; Phase 2 will migrate them to the shared helper.
Plotting
-
splot.netobjectnow routes on the Nestimate$methodslot rather than just direction. Undirected sequence-based networks frombuild_cna()andwtna(method = "cooccurrence")get oval TNA-family styling (layout, palette, donuts) with arrows and dotted edge starts automatically dropped because the matrix is symmetric. Glasso / cor / pcor / ising networks still getpsych_styling = TRUE(spring layout, Okabe-Ito palette). -
from_tna()auto-detects integer-valued weight matrices (ftna, ctna, raw counts) and setsweight_digits = edge_label_digits = 0so edge labels render as2304rather than2304.00. Fractional weights still format to two decimals. Explicit user-suppliedweight_digitsstill wins. -
psych_styling = TRUEis now exported as a first-class styling preset (undirected counterpart oftna_styling) — Okabe-Ito palette, spring layout, no arrows — applied by default tosplot.netobjecton correlation-family input and to the$contemporaneous/$betweenconstituents ofnet_mlvar. - Expanded
splot()dispatch coverage across the tna and Nestimate class hierarchies, ensuringtna,ftna,ctna,group_tna,tna_bootstrap,group_tna_bootstrap,tna_permutation,group_tna_permutation,netobject,netobject_group,netobject_ml,net_mlvar,wtna_mixed,net_bootstrap,net_permutation,boot_glasso,mcml,net_hon,net_hypa, andsimplicial_complexall reach the correct renderer. - Self-loops are now preserved in every plot function.
Correctness fixes (audit-driven)
-
detect_duplicate_edges(),aggregate_duplicate_edges(),simplify.cograph_network(), and the internalcheck_duplicate_edges()helper now respect directed vs undirected semantics. Previously the canonical (min/max) endpoint key collapsedA -> BandB -> Ainto one edge even on directed graphs, matchingigraph::simplify()ground truth. -
.compute_modularity()replaces a nested for loop with cluster-wise vectorization (sum(A[idx, idx]) - sum(k_out[idx]) * sum(k_in[idx]) / m), per the project “no for loops” rule. Results verified bit-exact againstigraph::modularity(). -
is_directed()now recognisesCographNetworkR6 objects — previously only thecograph_networklist format dispatched correctly. -
compute_layout_for_cograph()useslayout$get_type()instead of the removed$namefield onCographLayout. -
network_small_world()returns0(valid: no triangles means definitively not small-world) instead ofNA_real_when the observed clustering coefficient is zero but path length is finite. -
simplify.cograph_network()threads the directed flag through to edge aggregation so directed multigraphs collapse correctly.
Performance & documentation
-
simplify()performance refactor for large networks plus a cleaner title-composition path. -
motifs(),extract_motifs(), andplot.cograph_motif_analysisexamples reworked to usen_perm = 10L(orsignificance = FALSE) and promoted from\dontrunto CRAN-runnable (optional tna branches stay in\donttest). Retires 320 seconds of latent CRAN timing risk — every example now runs in under 4 seconds.
New tests
-
test-audit-fixes.R— ground-truth regressions for the directed edge semantics, modularity vectorization, and small-world behaviour changes. -
test-integer-weight-labels.R— locksfrom_tna()integer-weight auto-detect behaviour and precedence of explicitweight_digits. -
test-equiv-{assortativity, cluster-quality, communities, disparity, edge-centrality, network-summary, robustness, standalone-measures}.R— numerical equivalence against igraph, sna, centiserve, brainGraph, influenceR, tidygraph, and NetworkX. Gated byskip_coverage_tests() + skip_on_cran(), so they do not run on the CRAN pipeline.
cograph 2.1.0
New Features
Batch 6 — new-API graph-level / set-level / pair-level measures
These measures don’t fit the per-node centrality() data frame, so they live as standalone functions:
-
estrada_index()— graph-level spectral invariant: , equal to the trace of the matrix exponential of the adjacency. Equivalently, the sum ofsubgraph_centrality()across all nodes. Matchesnetworkx.estrada_indexat machine epsilon (max relative diff ~5e-15 across random test graphs). -
trophic_incoherence()— graph-level food-web stability measure (Johnson et al. 2014). Defined as the population standard deviation of per-edge trophic differences where is the trophic level of node . Zero for perfectly coherent DAGs (e.g., a pure chain). Matchesnetworkx.trophic_incoherence_parameterat machine epsilon. Directed-only; reuses the existingtrophic_levelcalculator. -
group_centrality(x, nodes, measure = c("betweenness", "closeness", "degree"))— Everett-Borgatti (1999) group centrality for a set of nodes. Returns a scalar. Supportsmode = "in"/"out"for directed-degree variants. Group closeness and group degree matchnetworkx.group_*_centralitybit-exact. Group betweenness implements the textbook Everett-Borgatti / Puzis 2008 definition (fraction of shortest paths passing through at least one node in the group), which diverges fromnetworkx.group_betweenness_centralityon some graphs due to a known quirk in NetworkX’s Puzis-Yahalom-Elovici iterative algorithm. Verified via an independent Python brute-force: cograph matches the textbook definition; NX produces larger values on graphs with many overlapping shortest paths. Documented in the roxygen “Divergence from NetworkX” section. -
dispersion(x, u = NULL, v = NULL, normalized = TRUE, alpha = 1, b = 0, c = 0)— Backstrom-Kleinberg (2014 Facebook) pair-level measure of tie strength. Counts the number of “well-dispersed” mutual friends ofuandv(pairs of common neighbors that are not directly connected and share no common neighbor insideu’s ego network other thanuandv). Matchesnetworkx.dispersionbit-exact across all 156 edges on the karate club graph. Returns a scalar, named vector, or data frame depending on which ofu,vare specified.
Centrality Batch 5 — Gould-Fernandez brokerage (5 roles)
Added the five Gould-Fernandez (1989) brokerage role counts, a foundational measure in social network analysis (~1500 citations). Each role is a separate per-node measure requiring a membership argument (following the same pattern as participation, within_module_z, gateway), and counts open directed 2-paths a -> v -> c through broker v:
-
centrality_brokerage_coordinator()— all three in broker’s group (w_I) -
centrality_brokerage_itinerant()— endpoints same group, broker different (w_O, “consultant”) -
centrality_brokerage_representative()— broker + source same, target different (b_IO) -
centrality_brokerage_gatekeeper()— broker + target same, source different (b_OI) -
centrality_brokerage_liaison()— all three in different groups (b_O)
Bit-exact match against sna::brokerage$raw.nli for all five roles across 20 random directed graphs. Implemented natively (no runtime dependency on sna). Key implementation detail: the Gould-Fernandez counting rule requires open 2-paths only — triads where a direct edge a -> c already exists are excluded. This matches sna’s C implementation exactly and was derived empirically (sna’s .C("brokerage_R", ...) has no R-level source).
Directed-only; warns and returns NA on undirected input.
Centrality Batch 4 — directed prestige family (Wasserman-Faust / sna)
-
centrality_prestige_domain()— directed-graph prestige measure: for each node , the number of other nodes that can reach via a directed path. Classical Wasserman-Faust (1994) measure fromsna::prestige(cmode = "domain"). Bit-exact match against sna, implemented natively viaigraph::distances(mode = "out")+colSums(is.finite(D)) - 1(no runtime dependency on sna). Directed-only; returns NA with a warning on undirected input. -
centrality_prestige_domain_proximity()— distance-weighted variant:R_v^2 / (D_v * (n - 1))whereR_vis the number of reachers andD_vis the sum of their geodesic distances tov. Bit-exact match againstsna::prestige(cmode = "domain.proximity")on strongly connected directed graphs. On graphs with any unreachable pair, sna has a known bug (FALSE * Inf = NaNcollapses the denominator, producing all-zero output); cograph’sis.finite()-masked formula produces mathematically correct values on any directed graph. Directed-only.
Centrality Batch 3 — classical measures with reference-package validation
-
centrality_katz()— Katz (1953) status index. Bit-exact match againstcentiserve::katzcent(cograph mirrors centiserve’s exact LAPACK call sequence). Also matchesigraph::alpha_centrality(exo = 1)andnetworkx.katz_centrality_numpyat machine epsilon. Newkatz_alphaparameter (default 0.1). -
centrality_hubbell()— Hubbell (1965) input-output centrality. Bit-exact match againstcentiserve::hubbell(cograph mirrors centiserve’s full-inverse LAPACK call path). Note: centiserve’s default (weights = NULL) silently ignoresE(g)$weight; to reproduce cograph’s behavior with centiserve on weighted graphs, passweights = igraph::E(g)$weightexplicitly. Newhubbell_weightparameter (default 0.5). -
centrality_information()— Stephenson-Zelen (1989) information centrality. Bit-exact match againstsna::infocenton connected undirected graphs (cograph mirrors sna’s exact construction andsolve()call sequence). -
centrality_pairwisedis()— Pairwise disconnectivity (Potapov et al. 2008). Directed-only; fraction of reachable ordered pairs that become unreachable when each node is removed. Bit-exact match againstcentiserve::pairwisedis. Warns and returnsNAon undirected input, matching the convention used bysalsa,leaderrank, andtrophic_level. -
centrality_reaching_local()/reaching_global()— Local and global reaching centrality (Mones, Vicsek & Vicsek 2012). Bit-exact match againstnetworkx.local_reaching_centralityacross the directed unweighted, undirected unweighted, and weighted branches. Undirected unweighted LRC coincides withigraph::harmonic_centrality(normalized = TRUE)(documented).reaching_global()is a graph-level hierarchy statistic in [0, 1].
cograph 1.8.2
New Features
-
plot_simplicial()now acceptstna,netobject,net_hon, andnet_hypaobjects directly — higher-order pathways are auto-built and visualized with proper state labels, no manual extraction needed. New parameters:method("hon"/"hypa"),max_pathways,ncol. Dismantled mode usesgridExtragrid layout with scaled nodes -
print.cograph_network()now shows a structured summary: node/edge counts, density, reciprocity, weight range, and top-degree nodes — replacing the minimal R6 default output - Added
mcmlS3 class withas_mcml()generic for type-safe handling of Markov Chain Multi-Level models — enablesprint(),plot(), and method dispatch on MCML objects - Added local
%||%operator for R 4.1 compatibility (no longer requires R 4.4+)
Breaking Changes
- MCML field names renamed for clarity:
$between→$macro,$within→$clusters -
as_tna()on MCML objects now returns a flatgroup_tnalist instead of a nested structure
Bug Fixes
-
plot_mcml()now suppresses zero-weight edges instead of drawing invisible lines, and strips leading zeros from edge labels (.32instead of0.32) - Self-loops in
cluster_summary()are now preserved in the macro diagonal, reflecting intra-cluster retention rates - Sequence data is properly propagated through the full tna → macro → cluster pipeline, so downstream models can use bootstrap and permutation tests
cograph 1.8.0
New Features
- Added
overlay_communities()for drawing community blob overlays on any network plot — accepts method names, membership vectors, or pre-computed community objects - Added
plot_simplicial()for higher-order pathway visualization, rendering simplicial complexes as smooth blobs with flexible separators and a dismantled view option - Added
value_nudgeparameter toplot_transitions()for controlling the distance between flow labels and nodes - Added bundle legend label controls:
bundle_legend_size,bundle_legend_color,bundle_legend_fontface,bundle_legend_position - Added per-function label controls (
label_size,label_color,label_fontface,label_hjust) toplot_transitions(),plot_trajectories(), andplot_alluvial()
cograph 1.7.0
New Features
Cluster Analysis
- Added
cluster_summary()for aggregating network weights at the cluster level, producing between-cluster and within-cluster matrices from raw transition data - Added
build_mcml()for constructing Markov Chain Multi-Level models from edge lists or sequence data with automatic cluster detection - Added
cluster_quality()for modularity-based cluster quality metrics andcluster_significance()for permutation-based significance testing - Added
as_tna()to convert cluster summaries to TNA objects for bootstrapping, permutation testing, and plotting withsplot()
Network Operations
- Added
simplify()for pruning weak edges from networks, with configurable weight threshold and aggregation method - Added
disparity_filter()for backbone extraction (Serrano et al. 2009), with methods for matrices, tna, igraph, and cograph_network objects - Added
robustness()for network robustness analysis with targeted (betweenness, degree) and random attack strategies, plusggplot_robustness()for faceted ggplot2 output - Added
temporal_edge_list()for converting sequence data to timestamped edge lists - Added
supra_adjacency(),supra_layer(),supra_interlayer()for multilayer supra-adjacency matrix construction - Added
layer_similarity(),layer_similarity_matrix(), andlayer_degree_correlation()for comparing layers in multilayer networks - Added
aggregate_weights()andaggregate_layers()for weight aggregation across layers - Added
verify_with_igraph()for cross-validating cograph centrality and network metrics against igraph
Motif Analysis
- Added
motifs()/subgraphs()as a unified API for triad census (node-exchangeable counts) and instance extraction (named node triples), with auto-detection of actor/session columns, rolling/tumbling window support, and exact configuration model significance testing
Visualization
- Added
plot_mcml()for Markov Chain Multi-Level visualization showing between-cluster summary edges alongside within-cluster detail, with pie charts, self-loops, and 22 customization parameters - Added
plot_chord()for native chord diagrams with automatic weight-based arc sizing - Added
plot_time_line()for cluster membership timeline visualization - Added
plot_htna()orientations:"facing"(tip-to-tip columns) and"circular"(two semicircles), plusintra_curvaturefor drawing intra-group edges as dotted bezier arcs - Added
thresholdparameter to all plot functions for filtering edges/cells below a minimum absolute weight - Added
value_fontface,value_fontfamily, andvalue_haloparameters toplot_heatmap()for text styling control - Added directional shorthands for
scale_nodes_by:indegree,outdegree,instrength,outstrength,incloseness,outcloseness,inharmonic,outharmonic,ineccentricity,outeccentricity - Added
scale_nodes_scaleparameter tosplot()for dampening (< 1) or exaggerating (> 1) centrality-based node sizing differences - Added qgraph argument translation in
splot(): when plotting tna objects, qgraph-style parameters (vsize,asize,edge.color,lty,shape) are automatically mapped to cograph equivalents
Transition Plot Enhancements
- Added intermediate labels with
node_label_format(e.g.,"{state} (n={count})") for showing counts on transition plot nodes - Added line bundling via
bundle_sizefor aggregating individual trajectories into weighted summary lines in large datasets - Added flow value labels via
show_values/value_positionfor displaying transition counts on flow lines - Added
label_positionconsistency across ALL columns (first, middle, last) in trajectory plots
Data & Infrastructure
- Added example datasets:
gamer_data,group_engagement,srl_data - Added
set_node_groups()/get_node_groups()for managing cluster assignments on cograph_network objects - Consolidated cograph_network metadata under
$metawith getter/setter functions - Added
group_tnasupport tosplot()for direct plotting of grouped TNA models - Gave each
centrality_*wrapper its own focused help page
Bug Fixes
- Fixed load and percolation centrality computation: the BFS assumed unit edge weights, causing infinite loops on weighted graphs; directed graphs now transpose correctly (matching sna convention); disconnected nodes no longer contribute spurious centrality
- Fixed self-loop and edge clipping in
splot()viewport calculation - Fixed argument forwarding in splot dispatch for bootstrap/permutation objects — named parameters (minimum, threshold, layout, title) were consumed by
splot()’s signature and silently dropped when dispatching - Fixed overlapping flow value labels in multi-step alluvial plots
- Fixed alluvial label halo rendering producing spike artifacts (8 → 16 offset directions)
- Fixed viridis palette direction in
plot_heatmap()so high values get dark colors - Fixed
build_mcml()density method crash when weight vector had no names - Fixed display label priority resolution (labels > label > identifier)
- Removed zero-value labels that appeared after rounding in transition plots
Improvements
- Simplified splot dispatch: extracted
.collect_dispatch_args()helper to replace 6 copy-paste dispatch blocks, usingmatch.call()+mget()for reliable argument capture
cograph 1.6.0
New Features
Centrality
- Added
centrality()with 23 measures and individual wrappers: degree, strength, betweenness, closeness, eigenvector, pagerank, harmonic, authority, hub, alpha, power, kreach, diffusion, percolation, eccentricity, transitivity, constraint, coreness, load, subgraph, leverage, laplacian, current-flow betweenness, current-flow closeness, voterank - Added
edge_betweenness()for edge-level centrality - Added automatic weight inversion for path-based measures when working with tna transition matrices (where higher weight = stronger connection, not shorter distance)
Community Detection
- Added
detect_communities()with 11 algorithms: louvain, walktrap, fast_greedy, label_propagation, leading_eigenvector, infomap, spinglass, leiden, optimal, edge_betweenness, multilevel — pluscom_*shorthand aliases - Added consensus clustering and
cluster_significance()for permutation-based validation
Network Metrics
- Added
network_summary()andsummarize_network()for computing comprehensive network-level statistics (density, reciprocity, transitivity, diameter, components, degree distribution)
Visualization
- Added
plot_transitions()for alluvial/Sankey flow diagrams, withplot_alluvial()andplot_trajectories()wrappers - Added
plot_bootstrap()andplot_permutation()for significance-styled visualization of bootstrap and permutation test results — significant edges rendered solid on top, non-significant edges dashed behind - Added
plot_mixed_network()for overlaying symmetric (undirected, straight) and asymmetric (directed, curved) edges on the same network - Added
plot_heatmap()for adjacency matrix heatmaps with optional hierarchical clustering andplot_ml_heatmap()for multilayer 3D perspective heatmaps - Added
plot_compare()for difference network visualization showing edge-weight changes between two networks - Added
splot()S3 methods fortna_bootstrapandtna_permutationobjects
Motif Analysis
- Added
motif_census(),triad_census(), andextract_motifs()for triad motif analysis with pattern filtering, significance testing, and network diagram visualization
Network Utilities
- Added
filter_edges(),subset_edges(),select_nodes(),select_edges()for flexible network subsetting - Added
set_groups()for storing cluster assignments on cograph_network objects with automatic dispatch toplot_htna()/plot_mtna()
Infrastructure
- All plot functions now accept
cograph_networkobjects as input, in addition to matrices, igraph objects, and tna objects - Layout computation is now lazy — coordinates are only calculated when first needed
- Improved
layout_springandlayout_gephi_fralgorithms: vectorized attraction forces, edge aggregation for dense networks - Renamed package from Sonnet to cograph
cograph 1.5.2
CRAN release: 2026-03-02
Breaking Changes
- Standardized first parameter name to
xacross all plotting functions:-
plot_tna():input→x -
plot_htna():input→x(wasmodel) -
plot_mtna():input→x(wasmodel) -
splot()already usedx
-
cograph 1.5.1
Breaking Changes (with backwards compatibility)
The following parameters have been renamed for consistency. The old names still work but emit deprecation warnings:
| Old Name | New Name | Reason |
|---|---|---|
esize |
edge_size |
Add edge_ prefix, expand abbreviation |
cut |
edge_cutoff |
Add edge_ prefix, clarify meaning |
usePCH |
use_pch |
Fix camelCase to snake_case |
positive_color |
edge_positive_color |
Add edge_ prefix (matches theme storage) |
negative_color |
edge_negative_color |
Add edge_ prefix (matches theme storage) |
donut_border_lty |
donut_line_type |
Expand lty abbreviation |
cograph 1.4.0
New Features
- Added
mlna()for multilevel network visualization with 3D perspective - Added
mtna()for multi-cluster network visualization with shape-based cluster containers - Added
plot_htna()for hierarchical multi-group network layouts with polygon and circular arrangements - Added
tplot()as a qgraph drop-in replacement with automatic parameter translation - Added
arrow_angleparameter for customizable arrowhead geometry
cograph 1.3.1
New Features
- Added
edge_start_dot_densityparameter for TNA-style dotted edge starts indicating direction - Added direct support for tna objects via
from_tna()— no manual matrix extraction needed - Added direct support for statnet
networkandqgraphobjects as input - Added auto-conversion of
pie_valuesvector todonut_fillwhen all values are in [0,1]
Bug Fixes
- Fixed TNA visual defaults being silently overwritten in
splot()when other parameters were specified - Fixed self-loop edge labels overlapping the loop arc
- Fixed
donut_shapevalidation rejecting custom SVG shapes - Fixed title clipping when title text exceeded plot margins
- Fixed edge rendering crash on certain edge/node configurations
- Removed underscore prefix requirement for custom SVG shape names
cograph 1.2.7
Bug Fixes
- Fixed oversized nodes in
from_qgraph()when a layout override was provided - Fixed oval layout using independent axis scaling, which distorted aspect ratios — now uses uniform scaling via
normalize_coords() - Fixed edge label alignment in
from_qgraph()by using a matrix intermediary for per-edge vector reordering - Fixed
nrow(el)crash: qgraph’s Edgelist is a list, not a data.frame - Fixed oval layout node distortion and donut fill values when converting from qgraph
cograph 1.2.6
New Features
- Added
donut_emptyparameter for rendering unfilled donut nodes - Added
from_qgraph()for converting qgraph objects to cograph format, reading resolvedgraphAttributesfor accurate parameter extraction
cograph 1.2.0
New Features
- Added
soplot()for grid/ggplot2-based network plotting — full feature parity withsplot()using a different rendering backend - Added
layout_oval()for oval/elliptical node arrangements - Added
layout_scaleparameter to expand or contract the network layout, with"auto"mode for node-count-based scaling - Added Gephi-style Fruchterman-Reingold layout algorithm
- Added
edge_start_styleparameter for visually indicating edge direction via styled start segments (dashed, dotted)
cograph 1.1.0
New Features
- Added
splot()— a base R graphics engine for network visualization usingpolygon(),lines(), andxspline(), providing better performance than grid-based rendering for large networks - Added polygon-shaped donut nodes, custom SVG node shapes, and AI-generated shape support
- Added shadow/halo labels and fine-grained text control (fontface, fontfamily, hjust, vjust, angle)
- Added double donut nodes with separate inner/outer border controls
- Added edge CI (confidence interval) underlays and template-based edge labels
- Added comprehensive legend support: groups, edge color scales, and node size scales
- Added high-resolution output via
sn_save()with configurable DPI - Added edge curve modes, bidirectional arrows, self-loop rotation, and per-edge curve control
Bug Fixes
- Fixed donut rendering producing artifacts and simplified the
donut_colorAPI to accept 1 color (fill), 2 colors (fill + background), or n colors (per-node) - Fixed arrow positioning and curve direction for qgraph-style edges
- Fixed edge label positioning to avoid overlap with edge lines
- Fixed self-loop rendering to use qgraph-style circular arcs
- Fixed arrow placement on non-square viewports
- Fixed reciprocal edge auto-separation causing edge crossings
