Introduction
The influencer package provides tools for calculating
influence scores of neurons in connectomes using linear dynamical
models. This vignette demonstrates the basic usage with simple synthetic
data that doesn’t require external authentication.
Basic Usage with Synthetic Data
Let’s create a simple network to demonstrate the core functionality:
# Create a simple 6-neuron network
edges <- data.frame(
pre = c("A", "B", "C", "D", "A", "B"),
post = c("B", "C", "D", "E", "C", "D"),
count = c(10, 8, 12, 6, 5, 15),
norm = c(0.5, 0.4, 0.6, 0.3, 0.25, 0.75)
)
meta <- data.frame(
root_id = c("A", "B", "C", "D", "E"),
cell_type = c("input", "interneuron", "interneuron", "output", "output"),
# `top_nt` is required by `signed = TRUE` (and by `excluded_nts`); we set
# it here so the signed-mode example below can run.
top_nt = c("acetylcholine", "gaba", "acetylcholine", "glutamate", "acetylcholine")
)
print("Edge list:")
#> [1] "Edge list:"
print(edges)
#> pre post count norm
#> 1 A B 10 0.50
#> 2 B C 8 0.40
#> 3 C D 12 0.60
#> 4 D E 6 0.30
#> 5 A C 5 0.25
#> 6 B D 15 0.75
print("Metadata:")
#> [1] "Metadata:"
print(meta)
#> root_id cell_type top_nt
#> 1 A input acetylcholine
#> 2 B interneuron gaba
#> 3 C interneuron acetylcholine
#> 4 D output glutamate
#> 5 E output acetylcholineCreating an Influence Calculator
# Create influence calculator using the R implementation
ic <- influence_calculator_r(edgelist_simple = edges, meta = meta)
# Print some information about the calculator
cat("Network has", nrow(ic$meta), "neurons and", nrow(ic$edgelist_simple), "connections\n")
#> Network has 5 neurons and connectionsCalculating Influence Scores
# Calculate influence of neuron "A" on the network
influence_scores_A <- ic$calculate_influence("A")
print("Influence of neuron A:")
#> [1] "Influence of neuron A:"
print(influence_scores_A)
#> matrix_index id is_seed Influence_score_(unsigned) adjusted_influence
#> 1 0 A TRUE 1.000000e+00 24.00000
#> 2 1 B FALSE 2.969840e+03 31.99626
#> 3 2 C FALSE 7.057443e+06 39.76959
#> 4 3 D FALSE 2.516460e+10 47.94870
#> 5 4 E FALSE 4.484089e+13 55.43414
# Calculate influence of neuron "B"
influence_scores_B <- ic$calculate_influence("B")
print("Influence of neuron B:")
#> [1] "Influence of neuron B:"
print(influence_scores_B)
#> matrix_index id is_seed Influence_score_(unsigned) adjusted_influence
#> 1 0 A FALSE 0.000000e+00 0.00000
#> 2 1 B TRUE 1.000000e+00 24.00000
#> 3 2 C FALSE 2.375872e+03 31.77312
#> 4 3 D FALSE 8.471604e+06 39.95223
#> 5 4 E FALSE 1.509558e+10 47.43767Visualizing Results
# Combine results for comparison
influence_scores_A$seed <- "A"
influence_scores_B$seed <- "B"
combined_results <- rbind(influence_scores_A, influence_scores_B)
# Create comparison plot
ggplot(combined_results, aes(x = id, y = adjusted_influence, fill = seed)) +
geom_col(position = "dodge") +
labs(
title = "Influence Scores Comparison",
subtitle = "Comparing influence propagation from neurons A and B",
x = "Target Neuron",
y = "Adjusted Influence Score",
fill = "Seed Neuron"
) +
theme_minimal() +
theme(axis.text.x = element_text(angle = 45, hjust = 1))
Multiple Seed Neurons
You can also calculate influence from multiple seed neurons simultaneously:
# Calculate influence from both A and B together
combined_influence <- ic$calculate_influence(c("A", "B"))
print("Combined influence from A and B:")
#> [1] "Combined influence from A and B:"
print(combined_influence)
#> matrix_index id is_seed Influence_score_(unsigned) adjusted_influence
#> 1 0 A TRUE 1.000000e+00 24.00000
#> 2 1 B TRUE 2.970840e+03 31.99660
#> 3 2 C FALSE 7.059819e+06 39.76993
#> 4 3 D FALSE 2.517307e+10 47.94904
#> 5 4 E FALSE 4.485599e+13 55.43448
# Compare individual vs combined influence
comparison <- merge(
influence_scores_A[, c("id", "adjusted_influence")],
combined_influence[, c("id", "adjusted_influence")],
by = "id",
suffixes = c("_A_only", "_A_and_B")
)
print(comparison)
#> id adjusted_influence_A_only adjusted_influence_A_and_B
#> 1 A 24.00000 24.00000
#> 2 B 31.99626 31.99660
#> 3 C 39.76959 39.76993
#> 4 D 47.94870 47.94904
#> 5 E 55.43414 55.43448Understanding the Results
The influence scores represent how much each neuron is affected by the seed neurons through the network dynamics. Key points:
- Raw influence scores: Direct output from the linear dynamical model
-
Adjusted influence:
max(0, log(influence_score) + 24)- provides a meaningful scale - Additive effects: Influence from multiple seeds combines linearly
Signed vs Unsigned Networks
The package supports both signed and unsigned connectivity:
# Create calculator with signed connectivity. The library has no per-organism
# default for which transmitters are inhibitory; you must supply
# `inhibitory_nts` explicitly when `signed = TRUE`. (`excluded_nts` is also
# accepted, for transmitter classes that gate both excitatory and inhibitory
# receptors and so cannot be assigned a single sign safely.)
ic_signed <- influence_calculator_r(
edgelist_simple = edges,
meta = meta,
signed = TRUE,
inhibitory_nts = c("glutamate", "gaba", "serotonin", "octopamine")
)
# Results will be similar for this example since we don't have inhibitory neurons marked
influence_signed <- ic_signed$calculate_influence("A")
print("Signed network influence (same as unsigned for this example):")
#> [1] "Signed network influence (same as unsigned for this example):"
print(head(influence_signed))
#> matrix_index id is_seed Influence_score_(signed) adjusted_influence
#> 1 0 A TRUE 1.000000e+00 24.00000
#> 2 1 B FALSE 2.812350e+03 31.94178
#> 3 2 C FALSE -6.326042e+06 -39.66019
#> 4 3 D FALSE -2.136112e+10 -47.78484
#> 5 4 E FALSE 3.604496e+13 55.21579Performance Notes
The R implementation includes smart caching - the first calculation does matrix decomposition, but subsequent calculations with the same network are much faster:
# Time the first calculation
system.time({
result1 <- ic$calculate_influence("A")
})
#> user system elapsed
#> 0.001 0.000 0.001
# Time a subsequent calculation (should be faster due to caching)
system.time({
result2 <- ic$calculate_influence("C")
})
#> user system elapsed
#> 0.001 0.000 0.000Next Steps
For real-world applications:
- Large networks: The package handles large connectomes efficiently
- Data formats: Supports both data frames and SQLite databases
- Python integration: Optional Python backend for specialized use cases
- Real data: See the BANC connectome analysis vignette for biological examples
Session Information
sessionInfo()
#> R version 4.6.1 (2026-06-24)
#> Platform: x86_64-pc-linux-gnu
#> Running under: Ubuntu 24.04.4 LTS
#>
#> Matrix products: default
#> BLAS: /usr/lib/x86_64-linux-gnu/openblas-pthread/libblas.so.3
#> LAPACK: /usr/lib/x86_64-linux-gnu/openblas-pthread/libopenblasp-r0.3.26.so; LAPACK version 3.12.0
#>
#> locale:
#> [1] LC_CTYPE=C.UTF-8 LC_NUMERIC=C LC_TIME=C.UTF-8
#> [4] LC_COLLATE=C.UTF-8 LC_MONETARY=C.UTF-8 LC_MESSAGES=C.UTF-8
#> [7] LC_PAPER=C.UTF-8 LC_NAME=C LC_ADDRESS=C
#> [10] LC_TELEPHONE=C LC_MEASUREMENT=C.UTF-8 LC_IDENTIFICATION=C
#>
#> time zone: UTC
#> tzcode source: system (glibc)
#>
#> attached base packages:
#> [1] stats graphics grDevices utils datasets methods base
#>
#> other attached packages:
#> [1] ggplot2_4.0.3 dplyr_1.2.1 influencer_2.0.0
#>
#> loaded via a namespace (and not attached):
#> [1] sass_0.4.10 generics_0.1.4 RSQLite_3.53.3 lattice_0.22-9
#> [5] digest_0.6.39 magrittr_2.0.5 evaluate_1.0.5 grid_4.6.1
#> [9] RColorBrewer_1.1-3 fastmap_1.2.0 blob_1.3.0 jsonlite_2.0.0
#> [13] Matrix_1.7-5 RSpectra_0.16-2 DBI_1.3.0 scales_1.4.0
#> [17] textshaping_1.0.5 jquerylib_0.1.4 cli_3.6.6 rlang_1.3.0
#> [21] bit64_4.8.2 withr_3.0.3 cachem_1.1.0 yaml_2.3.12
#> [25] otel_0.2.0 tools_4.6.1 memoise_2.0.1 reticulate_1.46.0
#> [29] vctrs_0.7.3 R6_2.6.1 png_0.1-9 lifecycle_1.0.5
#> [33] fs_2.1.0 htmlwidgets_1.6.4 bit_4.6.0 ragg_1.5.2
#> [37] pkgconfig_2.0.3 desc_1.4.3 pkgdown_2.2.1 pillar_1.11.1
#> [41] bslib_0.11.0 gtable_0.3.6 glue_1.8.1 Rcpp_1.1.2
#> [45] systemfonts_1.3.2 xfun_0.60 tibble_3.3.1 tidyselect_1.2.1
#> [49] knitr_1.51 farver_2.1.2 htmltools_0.5.9 labeling_0.4.3
#> [53] rmarkdown_2.31 compiler_4.6.1 S7_0.2.2