CorNetto builds knowledge-guided multi-omic correlation networks from normalized assay data stored in a MultiAssayExperiment. It is intended for workflows where transcriptomic, proteomic, metabolomic, or related assays are already normalized and the analysis question is whether groups differ in correlation structure, prior-supported connectivity, or node-level rewiring.
The package uses standard Bioconductor containers for assay and sample metadata, and returns standardized edge tables that can be combined, converted to igraph objects, or exported as Cytoscape-ready node and edge tables.
CorNetto is for downstream analysis after assay-level preprocessing. It uses Bioconductor containers, implements the Fisher z-difference test for differential correlation, and uses igraph for graph representation. The package adds the glue needed for prior-guided candidate-edge differential correlation, knowledge-network-aware integration, focused subnetworks, and rewiring summaries in a single reproducible workflow.
The Bioconductor package dcanr provides several methods and an evaluation framework for differential co-expression or association network inference. CorNetto has a narrower role. It works directly with MultiAssayExperiment, tests prespecified within- or cross-assay edges from heterogeneous prior networks, and carries those results through network integration and node-level rewiring summaries. It is therefore complementary to dcanr rather than a replacement for its method-comparison and benchmarking framework.
Green boxes are CorNetto functions, blue boxes are the objects they return, and orange boxes are inputs and the MultiAssayExperiment that carries results between steps.
The diagram outlines how the functions relate to one another. Inputs
(yellow) are read either by readKnowledgeNetwork(), for
prior-knowledge databases, or by createAnalysisData(), for
multi-omic abundance data and sample metadata. Each returns a
package-native object: a prior network, or a CorNetto
MultiAssayExperiment. From there the package builds
correlation networks, differential correlation networks, rewiring scores
and permuted rewiring scores.
The order shown is illustrative, not prescriptive. You could equally
run createDifferentialCorrelationNetwork(), narrow the
result with filterNetworkByNodes(), then call
createNetworkGraph() to obtain a focused
differential-correlation graph.
The bottom-right panel shows the two ways results are handled: a
function can return its result directly, or store it inside the CorNetto
MultiAssayExperiment, from which
getCorNettoResult() retrieves it by name. Both work; which
you use is a matter of preference.
The CorNetto workflow, from input data and prior knowledge through to rewiring validation and export.
After acceptance to Bioconductor, install CorNetto with:
analysisData <- exampleAnalysisData()
knowledgeNetwork <- exampleKnowledgeNetwork()
seedNodes <- exampleSeedNodes()
analysisData
#> A MultiAssayExperiment object of 3 listed
#> experiments with user-defined names and respective classes.
#> Containing an ExperimentList class object of length 3:
#> [1] protein: SummarizedExperiment with 5 rows and 20 columns
#> [2] transcript: SummarizedExperiment with 5 rows and 20 columns
#> [3] metabolite: SummarizedExperiment with 4 rows and 20 columns
#> Functionality:
#> experiments() - obtain the ExperimentList instance
#> colData() - the primary/phenotype DataFrame
#> sampleMap() - the sample coordination DataFrame
#> `$`, `[`, `[[` - extract colData columns, subset, or experiment
#> *Format() - convert into a long or wide DataFrame
#> assays() - convert ExperimentList to a SimpleList of matrices
#> exportClass() - save data to flat files
summarizeAnalysisData(analysisData, groupColumn = "clinicalGroup", quiet = TRUE)
#> $assays
#> DataFrame with 3 rows and 9 columns
#> assayName featureCount sampleCount missingValueCount missingValueFraction
#> <character> <integer> <integer> <integer> <numeric>
#> 1 protein 5 20 0 0
#> 2 transcript 5 20 0 0
#> 3 metabolite 4 20 0 0
#> zeroVarianceFeatureCount allMissingFeatureCount highMissingFeatureCount
#> <integer> <integer> <integer>
#> 1 0 0 0
#> 2 0 0 0
#> 3 0 0 0
#> samplesMissingFromColData
#> <integer>
#> 1 0
#> 2 0
#> 3 0
#>
#> $samples
#> $samples$overall
#> DataFrame with 1 row and 2 columns
#> sampleCount samplesInAnyAssay
#> <integer> <integer>
#> 1 20 20
#>
#> $samples$groups
#> DataFrame with 2 rows and 2 columns
#> groupLevel sampleCount
#> <character> <integer>
#> 1 PASC 10
#> 2 Recovered 10
#>
#>
#> $warnings
#> character(0)
head(knowledgeNetwork)
#> DataFrame with 6 rows and 30 columns
#> fromFeatureIdentifier toFeatureIdentifier fromFeatureName toFeatureName
#> <character> <character> <character> <character>
#> 1 P1 P2 CFH C3
#> 2 P1 P3 CFH CR1
#> 3 T1 T2 CFH transcript C3 transcript
#> 4 T1 P1 CFH transcript CFH
#> 5 T2 P2 C3 transcript C3
#> 6 M1 P1 Citrate CFH
#> fromAssayName toAssayName edgeType edgeDirection sourceType
#> <character> <character> <character> <character> <character>
#> 1 protein protein proteinProteinIntera.. undirected knowledge
#> 2 protein protein proteinProteinIntera.. undirected knowledge
#> 3 transcript transcript coexpressionPrior undirected knowledge
#> 4 transcript protein rnaProtein directed knowledge
#> 5 transcript protein rnaProtein directed knowledge
#> 6 metabolite protein proteinMetabolite directed knowledge
#> correlationScope correlationMethod knowledgeSource groupName
#> <character> <character> <character> <character>
#> 1 NA NA CorNettoSynthetic NA
#> 2 NA NA CorNettoSynthetic NA
#> 3 NA NA CorNettoSynthetic NA
#> 4 NA NA CorNettoSynthetic NA
#> 5 NA NA CorNettoSynthetic NA
#> 6 NA NA CorNettoSynthetic NA
#> comparisonName correlationValue group1CorrelationValue group2CorrelationValue
#> <character> <numeric> <numeric> <numeric>
#> 1 NA NA NA NA
#> 2 NA NA NA NA
#> 3 NA NA NA NA
#> 4 NA NA NA NA
#> 5 NA NA NA NA
#> 6 NA NA NA NA
#> pValue adjustedPValue group1PValue group2PValue group1AdjustedPValue
#> <numeric> <numeric> <numeric> <numeric> <numeric>
#> 1 NA NA NA NA NA
#> 2 NA NA NA NA NA
#> 3 NA NA NA NA NA
#> 4 NA NA NA NA NA
#> 5 NA NA NA NA NA
#> 6 NA NA NA NA NA
#> group2AdjustedPValue zScoreDifference sampleCount group1SampleCount
#> <numeric> <numeric> <numeric> <numeric>
#> 1 NA NA NA NA
#> 2 NA NA NA NA
#> 3 NA NA NA NA
#> 4 NA NA NA NA
#> 5 NA NA NA NA
#> 6 NA NA NA NA
#> group2SampleCount edgeWeight evidenceScore isDirected
#> <numeric> <numeric> <numeric> <logical>
#> 1 NA 0.95 0.95 FALSE
#> 2 NA 0.92 0.92 FALSE
#> 3 NA 0.80 0.80 FALSE
#> 4 NA 1.00 1.00 TRUE
#> 5 NA 1.00 1.00 TRUE
#> 6 NA 0.88 0.88 TRUE
seedNodes
#> [1] "P1" "T1" "M1"The synthetic example contains three assays named
protein, transcript, and
metabolite. The example prior network also contains a
drug-target edge to demonstrate that prior networks can include static
knowledge beyond the measured assays. Prior-guided candidate-edge
analyses must therefore be given only prior edges whose assay names are
present in the analysis object.
createCorrelationNetwork() computes all pairwise
within-omic correlations for one assay and one group. Dense all-pairs
mode is intended for small-to-medium assays; for large assays, prefer
prior-guided candidate-edge testing when suitable.
recoveredProteinNetwork <- createCorrelationNetwork(
analysisData = analysisData,
assayName = "protein",
groupColumn = "clinicalGroup",
groupLevel = "Recovered",
correlationMethod = "pearson",
minimumAbsoluteCorrelation = 0,
adjustedPValueThreshold = 1,
pAdjustMethod = "fdr",
storeResult = FALSE
)
head(recoveredProteinNetwork)
#> DataFrame with 6 rows and 30 columns
#> fromFeatureIdentifier toFeatureIdentifier fromFeatureName toFeatureName
#> <character> <character> <character> <character>
#> 1 P1 P2 CFH C3
#> 2 P1 P3 CFH CR1
#> 3 P2 P3 C3 CR1
#> 4 P1 P4 CFH CFB
#> 5 P2 P4 C3 CFB
#> 6 P3 P4 CR1 CFB
#> fromAssayName toAssayName edgeType edgeDirection sourceType
#> <character> <character> <character> <character> <character>
#> 1 protein protein correlation positive correlation
#> 2 protein protein correlation positive correlation
#> 3 protein protein correlation positive correlation
#> 4 protein protein correlation negative correlation
#> 5 protein protein correlation negative correlation
#> 6 protein protein correlation negative correlation
#> correlationScope correlationMethod knowledgeSource groupName comparisonName
#> <character> <character> <character> <character> <character>
#> 1 withinOmic pearson NA Recovered NA
#> 2 withinOmic pearson NA Recovered NA
#> 3 withinOmic pearson NA Recovered NA
#> 4 withinOmic pearson NA Recovered NA
#> 5 withinOmic pearson NA Recovered NA
#> 6 withinOmic pearson NA Recovered NA
#> correlationValue group1CorrelationValue group2CorrelationValue pValue
#> <numeric> <numeric> <numeric> <numeric>
#> 1 0.878752 NA NA 0.000814789
#> 2 0.747338 NA NA 0.012972274
#> 3 0.787569 NA NA 0.006833154
#> 4 -0.431744 NA NA 0.212790881
#> 5 -0.509253 NA NA 0.132731940
#> 6 -0.475459 NA NA 0.164878371
#> adjustedPValue group1PValue group2PValue group1AdjustedPValue
#> <numeric> <numeric> <numeric> <numeric>
#> 1 0.00226296 NA NA NA
#> 2 0.02162046 NA NA NA
#> 3 0.01366631 NA NA NA
#> 4 0.23643431 NA NA NA
#> 5 0.18961706 NA NA NA
#> 6 0.20609796 NA NA NA
#> group2AdjustedPValue zScoreDifference sampleCount group1SampleCount
#> <numeric> <numeric> <numeric> <numeric>
#> 1 NA NA 10 NA
#> 2 NA NA 10 NA
#> 3 NA NA 10 NA
#> 4 NA NA 10 NA
#> 5 NA NA 10 NA
#> 6 NA NA 10 NA
#> group2SampleCount edgeWeight evidenceScore isDirected
#> <numeric> <numeric> <numeric> <logical>
#> 1 NA 0.878752 NA FALSE
#> 2 NA 0.747338 NA FALSE
#> 3 NA 0.787569 NA FALSE
#> 4 NA -0.431744 NA FALSE
#> 5 NA -0.509253 NA FALSE
#> 6 NA -0.475459 NA FALSEtestDifferentialCorrelation() can test only feature
pairs supported by a prior network when candidateEdgeTable
is supplied. This is the sparse mode for differential correlation: it
avoids exhaustive cross-omic testing and keeps the dynamic network
aligned to interpretable prior knowledge.
priorGuidedDifferentialResults <- testDifferentialCorrelation(
analysisData = analysisData,
candidateEdgeTable = measuredKnowledgeNetwork,
groupColumn = "clinicalGroup",
groupLevels = c("PASC", "Recovered"),
minimumAbsoluteCorrelation = 0,
adjustedPValueThreshold = 1,
pAdjustMethod = "fdr",
storeResult = FALSE
)
priorGuidedDifferentialNetwork <- createDifferentialCorrelationNetwork(
differentialCorrelationTable = priorGuidedDifferentialResults,
minimumAbsoluteCorrelation = 0
)
c(nrow(priorGuidedDifferentialResults), nrow(priorGuidedDifferentialNetwork))
#> [1] 7 7permuteRewiringScores() permutes group labels,
recomputes the differential-correlation statistics over a fixed edge
universe, and compares each node’s observed rewiring score with the
permutation distribution. When both candidateEdgeTable and
assayName are omitted, that universe is built from dense
within-omic pairs in every assay; cross-omic pairs are not
generated.
The fixed edge set is attempted in every permutation. An edge can
still be unscored if a permuted group has insufficient pairwise-complete
data or a constant feature, and contributingPermutations
records the resulting loss. Supplying candidateEdgeTable
with all observed-data filters disabled, as below, lets CorNetto fix the
candidate universe before inspecting the group labels. The result is
marked as a randomization p-value only when every edge and the selected
node score are estimable under the permitted allocations. The user is
still responsible for prespecifying the candidates and for the
exchangeability assumption.
backend <- BiocParallel::SnowParam(workers = 2, type = "SOCK")
rewiringValidation <- permuteRewiringScores(
analysisData = analysisData,
candidateEdgeTable = measuredKnowledgeNetwork,
groupColumn = "clinicalGroup",
groupLevels = c("PASC", "Recovered"),
minimumAbsoluteCorrelation = 0,
adjustedPValueThreshold = NULL,
pAdjustMethod = "fdr",
nPermutations = 99,
seed = 1,
# Remove the three lines below to run serially:
verbose = TRUE,
progressEvery = 50,
BPPARAM = backend
)
#> Scoring 99 permutations with 2 workers.
#> Completed 50 of 99 permutations (50.5%).
#> Completed 99 of 99 permutations (100.0%).
head(rewiringValidation$rewiringTable)
#> DataFrame with 6 rows and 18 columns
#> nodeKey nodeIdentifier nodeName assayName totalConnections
#> <character> <character> <character> <character> <integer>
#> 1 protein::P1 P1 CFH protein 4
#> 2 transcript::T1 T1 CFH transcript transcript 2
#> 3 transcript::T2 T2 C3 transcript transcript 2
#> 4 metabolite::M1 M1 Citrate metabolite 1
#> 5 metabolite::M2 M2 Succinate metabolite 1
#> 6 protein::P2 P2 C3 protein 3
#> rawRewiringScore rootMeanSquareRewiringScore degreeBin degreeMatchedZScore
#> <numeric> <numeric> <character> <numeric>
#> 1 2.58494 1.29247 (2,3] NA
#> 2 1.83367 1.29660 (1,2] NA
#> 3 2.51915 1.78131 (1,2] NA
#> 4 0.71149 0.71149 [0,1] NA
#> 5 1.40686 1.40686 [0,1] NA
#> 6 2.97487 1.71754 (1,2] NA
#> permutationTailProbability adjustedPermutationTailProbability nullMeanScore
#> <numeric> <numeric> <numeric>
#> 1 0.06 0.140 1.476106
#> 2 0.14 0.175 1.094358
#> 3 0.14 0.175 1.373130
#> 4 0.26 0.260 0.554030
#> 5 0.02 0.140 0.567395
#> 6 0.05 0.140 1.391005
#> nullSdScore contributingPermutations scoreColumn nPermutations
#> <numeric> <integer> <character> <integer>
#> 1 0.570168 99 rawRewiringScore 99
#> 2 0.578007 99 rawRewiringScore 99
#> 3 0.792259 99 rawRewiringScore 99
#> 4 0.431635 99 rawRewiringScore 99
#> 5 0.353340 99 rawRewiringScore 99
#> 6 0.736635 99 rawRewiringScore 99
#> blockColumn inferenceStatus
#> <character> <character>
#> 1 NA randomization p-value
#> 2 NA randomization p-value
#> 3 NA randomization p-value
#> 4 NA randomization p-value
#> 5 NA randomization p-value
#> 6 NA randomization p-value
rewiringValidation$inferenceStatus
#> [1] "randomization p-value"For a fully scored node, the smallest tail probability is
1 / (nPermutations + 1), so 99 permutations bottom out at
0.01. contributingPermutations records how many
permutations produced a score for each node. Treat the values as
conditional rankings whenever inferenceStatus says so.
The call above uses a BiocParallel
socket backend, which is the portable choice on Windows. Keep examples
and automated checks at two workers or fewer. verbose and
progressEvery control progress reporting;
BPPARAM selects the backend. A fixed seed
gives the same label allocations whatever the worker count, so serial
and parallel runs agree numerically.
testDifferentialCorrelation() compares correlation
coefficients between two groups.
createDifferentialCorrelationNetwork() converts the test
results to a weighted network, and
calculateRewiringScores() summarizes node-level rewiring.
When assayName is omitted, every assay is tested, but pairs
are generated only within each assay: protein-protein and
transcript-transcript pairs are included, for example, whereas
protein-transcript pairs are not.
differentialResults <- testDifferentialCorrelation(
analysisData = analysisData,
groupColumn = "clinicalGroup",
groupLevels = c("PASC", "Recovered"),
correlationMethod = "pearson",
minimumAbsoluteCorrelation = 0,
adjustedPValueThreshold = 1,
pAdjustMethod = "fdr",
storeResult = FALSE
)
differentialNetwork <- createDifferentialCorrelationNetwork(
differentialCorrelationTable = differentialResults,
minimumAbsoluteCorrelation = 0
)
rewiringScores <- calculateRewiringScores(
differentialCorrelationNetwork = differentialNetwork,
storeResult = FALSE
)
head(rewiringScores)
#> DataFrame with 6 rows and 9 columns
#> nodeKey nodeIdentifier nodeName assayName totalConnections
#> <character> <character> <character> <character> <integer>
#> 1 protein::P3 P3 CR1 protein 4
#> 2 protein::P1 P1 CFH protein 4
#> 3 protein::P2 P2 C3 protein 4
#> 4 protein::P4 P4 CFB protein 4
#> 5 transcript::T1 T1 CFH transcript transcript 4
#> 6 transcript::T3 T3 CR1 transcript transcript 4
#> rawRewiringScore rootMeanSquareRewiringScore degreeBin degreeMatchedZScore
#> <numeric> <numeric> <character> <numeric>
#> 1 6.18963 3.09481 (2,3] 0.968730
#> 2 5.71175 2.85588 (2,3] 0.768908
#> 3 4.81787 2.40894 (2,3] 0.395134
#> 4 2.79769 1.39884 (2,3] -0.449601
#> 5 2.61704 1.30852 (2,3] -0.525138
#> 6 2.73210 1.36605 (2,3] -0.477028The three scores are descriptive, not tests.
rawRewiringScore is the L2 norm of a node’s incident
z-scores and grows with degree. rootMeanSquareRewiringScore
divides that by sqrt(degree) and is the one to compare
across nodes of different degree. degreeMatchedZScore
standardizes within bins of log2(degree + 1), so it is a
within-bin ranking aid rather than a z-score against a null model; it is
NA for bins holding fewer than five nodes, since a smaller
bin cannot produce a meaningful spread.
permuteRewiringScores() adds a permutation reference; its
inferenceStatus states whether the result meets the
computational conditions for randomization inference.
Features are mutually tested only against features in the same assay. In this example, each protein and transcript node therefore has degree four, while each metabolite node has degree three. On a real network with a spread of degrees, the bins do the work they are named for.
combineNetworks() merges static prior knowledge,
group-specific correlation layers, and differential-correlation layers.
createFocusedNetwork() extracts a seed-centered
neighborhood, which is useful for pathway-driven analyses.
integratedNetwork <- combineNetworks(
knowledgeNetwork = knowledgeNetwork,
correlationNetwork = recoveredProteinNetwork,
differentialCorrelationNetwork = list(
priorGuidedDifferentialNetwork,
differentialNetwork
),
includeReverseEdges = TRUE
)
focusedNetwork <- createFocusedNetwork(
networkEdgeTable = integratedNetwork,
seedNodes = seedNodes,
neighborhoodOrder = 1
)
cytoscapeTables <- prepareCytoscapeTables(
networkEdgeTable = focusedNetwork,
rewiringTable = rewiringScores
)
names(cytoscapeTables)
#> [1] "nodes" "edges"
nrow(cytoscapeTables$nodes)
#> [1] 14
nrow(cytoscapeTables$edges)
#> [1] 96createNetworkGraph() converts a standardized CorNetto
edge table to an igraph object.
Plotting can then use standard igraph methods.
A node is one feature in one assay, drawn with an assay-specific colour and shape. An edge is a connection between two features. Node colour could equally encode a rewiring score, a permutation tail probability, or any other node-level column.
displayGraph <- igraph::simplify(
igraph::as_undirected(createNetworkGraph(focusedNetwork), mode = "collapse")
)
assayStyle <- data.frame(
assay = c("protein", "transcript", "metabolite"),
colour = c("#2B8CBE", "#31A354", "#E6842A"),
shape = c("circle", "square", "csquare")
)
idx <- match(igraph::V(displayGraph)$assayName, assayStyle$assay)
set.seed(1)
plot(
displayGraph,
layout = igraph::layout_with_fr(displayGraph),
vertex.color = assayStyle$colour[idx],
vertex.shape = assayStyle$shape[idx],
vertex.label = igraph::V(displayGraph)$nodeName,
vertex.label.cex = 0.7,
vertex.label.color = "black",
vertex.label.family = "sans",
vertex.frame.color = "white",
vertex.size = 20,
edge.color = "grey65",
main = "Focused CorNetto network around the seed nodes"
)
legend(
"bottomleft",
legend = assayStyle$assay,
pt.bg = assayStyle$colour,
pch = c(21, 22, 23),
pt.cex = 1.6,
bty = "n",
title = "Assay"
)c(nodes = igraph::gorder(displayGraph),
connections = igraph::gsize(displayGraph))
#> nodes connections
#> 14 30The 96 exported edge rows reduce to 30 drawn connections for two reasons, and no edge is filtered out on the way.
First, combineNetworks(includeReverseEdges = TRUE)
stores each undirected edge in both directions, which accounts for most
of the difference. Reverse copies are added for undirected edges only.
This is a workaround rather than a claim about biology: several
Cytoscape algorithms require an explicit direction to traverse an edge,
while the edges themselves are not inherently directed, as with a
correlation or a protein-protein interaction. Storing both orientations
lets those algorithms move either way across such an edge. Genuinely
directed edges are left untouched.
Second, one feature pair can carry several rows when more than one layer supports it, since prior knowledge, a group-specific correlation and a differential-correlation result are separate rows describing the same pair.
The display graph shows one line per connected pair; the exported tables keep every row.
Use writeNetworkTables() when Cytoscape-ready files are needed. The
example writes to a temporary directory.
citation("CorNetto")
#> To cite CorNetto in publications, use:
#>
#> Ward B, Balligand J-L, Bamps L, Bommer G, Cani PD, De Greef J, Dewulf
#> JP, Gatto L, Haufroid V, Kabamba B, Pyr dit Ruys S, Vertommen D,
#> Yombi JC, Belkhir L, Elens L (2026). Longitudinal multi-omic network
#> rewiring at the complement-coagulation interface in post-acute
#> sequelae of COVID-19 (PASC). medRxiv. doi:
#> 10.64898/2026.07.14.26358048.
#>
#> A BibTeX entry for LaTeX users is
#>
#> @Article{,
#> title = {Longitudinal multi-omic network rewiring at the complement-coagulation interface in post-acute sequelae of COVID-19 (PASC)},
#> author = {Bradley Ward and Jean-Luc Balligand and Laurence Bamps and Guido Bommer and Patrice D. Cani and Julien {De Greef} and Joseph P. Dewulf and Laurent Gatto and Vincent Haufroid and Benoît Kabamba and Sébastien {Pyr dit Ruys} and Didier Vertommen and Jean Cyr Yombi and Leïla Belkhir and Laure Elens},
#> journal = {medRxiv},
#> year = {2026},
#> doi = {10.64898/2026.07.14.26358048},
#> }
#>
#> Leïla Belkhir and Laure Elens are joint senior authors.sessionInfo()
#> R version 4.6.1 (2026-06-24)
#> Platform: x86_64-pc-linux-gnu
#> Running under: Ubuntu 26.04.1 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.32.so; LAPACK version 3.12.0
#>
#> locale:
#> [1] LC_CTYPE=en_US.UTF-8 LC_NUMERIC=C
#> [3] LC_TIME=en_US.UTF-8 LC_COLLATE=en_US.UTF-8
#> [5] LC_MONETARY=en_US.UTF-8 LC_MESSAGES=en_US.UTF-8
#> [7] LC_PAPER=en_US.UTF-8 LC_NAME=C
#> [9] LC_ADDRESS=C LC_TELEPHONE=C
#> [11] LC_MEASUREMENT=en_US.UTF-8 LC_IDENTIFICATION=C
#>
#> time zone: Etc/UTC
#> tzcode source: system (glibc)
#>
#> attached base packages:
#> [1] stats graphics grDevices utils datasets methods base
#>
#> other attached packages:
#> [1] CorNetto_0.99.1 BiocStyle_2.41.0
#>
#> loaded via a namespace (and not attached):
#> [1] sass_0.4.10 generics_0.1.4
#> [3] SparseArray_1.13.2 lattice_0.23-1
#> [5] digest_0.6.39 magrittr_2.0.5
#> [7] evaluate_1.0.5 grid_4.6.1
#> [9] fastmap_1.2.0 jsonlite_2.0.0
#> [11] Matrix_1.7-6 BiocManager_1.30.27
#> [13] codetools_0.2-20 jquerylib_0.1.4
#> [15] abind_1.4-8 cli_3.6.6
#> [17] rlang_1.3.0 XVector_0.53.0
#> [19] Biobase_2.73.2 withr_3.0.3
#> [21] cachem_1.1.0 DelayedArray_0.39.6
#> [23] yaml_2.3.12 otel_0.2.0
#> [25] BiocBaseUtils_1.15.1 S4Arrays_1.13.0
#> [27] tools_4.6.1 parallel_4.6.1
#> [29] BiocParallel_1.47.0 SummarizedExperiment_1.43.0
#> [31] BiocGenerics_0.59.12 MultiAssayExperiment_1.39.1
#> [33] buildtools_1.0.0 R6_2.6.1
#> [35] matrixStats_1.5.0 stats4_4.6.1
#> [37] lifecycle_1.0.5 Seqinfo_1.3.2
#> [39] S4Vectors_0.51.10 IRanges_2.47.5
#> [41] pkgconfig_2.0.3 bslib_0.12.0
#> [43] xfun_0.60 GenomicRanges_1.65.4
#> [45] sys_3.4.3 MatrixGenerics_1.25.0
#> [47] knitr_1.52 htmltools_0.5.9
#> [49] snow_0.4-4 igraph_2.3.3
#> [51] rmarkdown_2.32 maketools_1.3.2
#> [53] compiler_4.6.1