oaqc/ 0000755 0001762 0000144 00000000000 14700737462 011207 5 ustar ligges users oaqc/tests/ 0000755 0001762 0000144 00000000000 14677305315 012352 5 ustar ligges users oaqc/tests/testthat/ 0000755 0001762 0000144 00000000000 14700737462 014211 5 ustar ligges users oaqc/tests/testthat/test-oaqc.R 0000644 0001762 0000144 00000001103 14677306124 016227 0 ustar ligges users test_that("oaqc works", {
coC4 <- data.frame(
source = c(0, 2),
target = c(1, 3)
)
coC4orbits <- oaqc(coC4, non_ind_freq = FALSE)
expect_true(all(coC4orbits$n_orbits_ind[, 4] == 1))
expect_true(all(coC4orbits$e_orbits_ind[, 2] == 1))
expect_error(oaqc("graph"))
k4 <- as.matrix(data.frame(
source = c(0, 0, 0, 1, 1, 2),
target = c(1, 2, 3, 2, 3, 3)
))
k4orbits <- oaqc(k4, non_ind_freq = FALSE)
expect_true(all(k4orbits$n_orbits_ind[, 20] == 1))
expect_true(all(k4orbits$e_orbits_ind[, 14] == 1))
})
oaqc/tests/testthat.R 0000644 0001762 0000144 00000000604 14677305315 014335 0 ustar ligges users # This file is part of the standard setup for testthat.
# It is recommended that you do not modify it.
#
# Where should you do additional test configuration?
# Learn more about the roles of various files in:
# * https://r-pkgs.org/testing-design.html#sec-tests-files-overview
# * https://testthat.r-lib.org/articles/special-files.html
library(testthat)
library(oaqc)
test_check("oaqc")
oaqc/MD5 0000644 0001762 0000144 00000002271 14700737462 011521 0 ustar ligges users 2eae1980d7bcabfe6023d290de250353 *DESCRIPTION
e87b550441993ea6df5f98497da449df *NAMESPACE
324c7d7896b7933c888d451b6f83b2e2 *NEWS.md
a029bb9e509983a34a0ddea24727fba7 *R/oaqc.R
70a34c6e2cbe3e9aae6cabe7066ffc71 *README.md
aa5e5a2cbfaea3d9b6cdbe378ac48cee *build/partial.rdb
968e50937d1e6721e7570edda3769b86 *build/vignette.rds
e0fa004a584de829f068b440e388387f *inst/CITATION
35bf01cb27020a2f94243da26fb92aa3 *inst/doc/oaqc.R
3f9162f6c039feace6e0430885cca698 *inst/doc/oaqc.Rmd
976b3117c819cb14a3cff5bcbd4adf18 *inst/doc/oaqc.html
951255bc9940f9a0b7474cf60c1e4f04 *man/annotate_result.Rd
9f43fca0155550166f49dff3df610e16 *man/as.edge_list.Rd
bc3347019390f3be5605d963c75aa9d2 *man/figures/logo.png
c94cc0d66e950fdef762b86d6f29f729 *man/oaqc.Rd
0f8e051f005a98eb1208ba412cc99182 *src/Graph.cpp
1a7fe775551c166fd3fbbab2ef9a4282 *src/Graph.h
a214bebab822e7bd9490b30ca01264d1 *src/QuadCensus.cpp
7d830d45ff00e5318585128b459889c8 *src/QuadCensus.h
cfb108949381a6d08ae23af65bce4acf *src/init.cpp
d00c8f3b6e8a430be1f7659627b8923e *tests/testthat.R
03bf4fc6668a5276231dbcce32fb4eff *tests/testthat/test-oaqc.R
3f9162f6c039feace6e0430885cca698 *vignettes/oaqc.Rmd
030bf730b7fd86c36f93b19122c74438 *vignettes/quad_census.svg
oaqc/R/ 0000755 0001762 0000144 00000000000 14674505364 011414 5 ustar ligges users oaqc/R/oaqc.R 0000644 0001762 0000144 00000006761 14674507560 012474 0 ustar ligges users #' @title Orbit-aware Quad Census computation
#' @name oaqc
#' @useDynLib oaqc, .registration=T
"_PACKAGE"
#' Coerce graph input.
#'
#' @param graph A matrix, data.frame or graph object.
#' @return Edge list matrix.
as.edge_list <- function(graph) {
if (is.matrix(graph)) {
if (length(dim(graph)) != 2 && ncol(graph) != 2) {
stop(paste(
"not coercable to edge list",
"only matrices with 2 columns supported"
))
}
graph
} else if (is.data.frame(graph)) {
if (ncol(graph) != 2) {
stop(paste(
"not coercable to edge list",
"only data frames with 2 columns supported"
))
}
data.matrix(graph)
} else if (inherits(graph, "igraph") && requireNamespace("igraph", quietly = TRUE)) {
igraph::as_edgelist(graph) - 1
} else {
stop(paste(
"unrecognized graph type",
"use matrix/data frame with 2 columns or igraph objects"
))
}
}
#' Annotates the igraph object with orbit labels.
#'
#' @param graph Unmodified input graph.
#' @param orbits List with n_orbits, e_orbits matrices.
#' @param non_ind_freq A flag indicating whether non-induced frequencies have to be written or not.
#' @return \code{orbits} if the input is not an igraph, the annotated igraph
#' instead.
annotate_result <- function(graph, orbits, non_ind_freq) {
if (inherits(graph, "igraph") && requireNamespace("igraph", quietly = T)) {
for (i in seq_len(ncol(orbits$n_orbits_ind))) {
graph <- igraph::set_vertex_attr(graph,
paste("orbit_ind", i, sep = "_"),
value = orbits$n_orbits_ind[, i]
)
}
for (i in seq_len(col(orbits$e_orbits_ind))) {
graph <- igraph::set_edge_attr(graph,
paste("orbit_ind", i, sep = "_"),
value = orbits$e_orbits_ind[, i]
)
}
if (non_ind_freq) {
for (i in seq_len(ncol(orbits$`n_orbits_non_ind`))) {
graph <- igraph::set_vertex_attr(graph,
paste("orbit_non_ind", i, sep = "_"),
value = orbits$`n_orbits_non_ind`[, i]
)
}
for (i in seq_len(ncol(orbits$`e_orbits_non_ind`))) {
graph <- igraph::set_edge_attr(graph,
paste("orbit_non_ind", i, sep = "_"),
value = orbits$`e_orbits_non_ind`[, i]
)
}
}
return(graph)
}
return(orbits)
}
#' Calculates the orbit-aware quad census on an edge and node level, see
#' \code{vignette('oaqc')}.
#'
#' @param graph A matrix, data.frame or graph object.
#' @param non_ind_freq A flag indicating whether non-induced frequencies have to be returned or not.
#' @param file Name (and location) of the file to be written.
#' @return orbit-aware quad census on a node and edge level. Consult
#' \code{vignette('oaqc')} to see the correspondence between orbit and quad.
#' @examples
#' k4 <- data.frame(
#' source = c(0, 0, 0, 1, 1, 2),
#' target = c(1, 2, 3, 2, 3, 3)
#' )
#'
#' k4orbits <- oaqc(k4, non_ind_freq = TRUE)
#' print(k4orbits)
#' @export
oaqc <- function(graph, non_ind_freq = F, file = "") {
edges <- as.edge_list(graph)
orbits <- .Call(
entry, as.integer(max(edges) + 1), as.integer(edges),
as.logical(non_ind_freq), as.character(file)
)
return(annotate_result(graph, orbits, as.logical(non_ind_freq)))
}
oaqc/vignettes/ 0000755 0001762 0000144 00000000000 14700723647 013217 5 ustar ligges users oaqc/vignettes/oaqc.Rmd 0000644 0001762 0000144 00000003234 14674530710 014605 0 ustar ligges users ---
title: "Introduction to oaqc"
author: "Mark Ortmann"
output: rmarkdown::html_vignette
vignette: >
%\VignetteIndexEntry{oaqc}
%\VignetteEngine{knitr::rmarkdown}
%\VignetteEncoding{UTF-8}
---
# Introduction to oaqc
This package provides an efficient algorithm to calculate for a given graph the **o**rbit-**a**ware **q**uad **c**ensus. More precisely the frequency distribution of all induced and non-induced non-isomorphic four node subgraphs, i.e. quads, on a node and edge level; see the figure below for the relation between orbit and quad.

## Input
The input can either be an edgelist (matrix or data.frame) or a graph Object ('igraph')
Despite the input format the graph should not contain loops
or multi-edges and the vertex indices have to lie in range
[0,n-1) with n denoting the number of vertices in the graph.
Note that if the smallest index is 1 the algorithm will create
an isolated vertex with index 0.
## Calculating the orbit-aware quad census
The following code exemplifies the use of this package.
```{r}
library(oaqc)
### k4, pure R
k4 <- data.frame(
source = c(0, 0, 0, 1, 1, 2),
target = c(1, 2, 3, 2, 3, 3)
)
k4orbits <- oaqc(k4, non_ind_freq = FALSE, file = "")
# print(k4orbits)
```
In order to calculate the non-induced frequencies as well just set the corresponding flag to `TRUE`.
Since the orbit-aware frequencies can be rather large integers, which can cause some problems with R, the results can be directly written to a file.
## Result
The results of the, e.g., induced frequencies of the nodes in orbit 10 can be accessed in the following way.
```{r}
print(k4orbits$n_orbits_ind[, 10])
``` oaqc/vignettes/quad_census.svg 0000644 0001762 0000144 00000235732 13202564173 016257 0 ustar ligges users