Skip to content

Commit

Permalink
Merge branch 'release/0.4.0'
Browse files Browse the repository at this point in the history
  • Loading branch information
ErdaradunGaztea committed Dec 17, 2021
2 parents 347ff8a + 5ed8eee commit fe999ad
Show file tree
Hide file tree
Showing 36 changed files with 1,327 additions and 92,941 deletions.
2 changes: 1 addition & 1 deletion .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ jobs:
command: |
mkdir -p ~/R/Library
Rscript -e 'install.packages("remotes")'
Rscript -e 'remotes::install_deps(dependencies = TRUE)'
Rscript -e 'remotes::install_deps(dependencies = TRUE, repos = c(getOption("repos"), remotes::bioc_install_repos()))'
- run:
name: Session information and installed package versions
command: |
Expand Down
19 changes: 9 additions & 10 deletions DESCRIPTION
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Package: deepdep
Title: Visualise and Explore the Deep Dependencies of R Packages
Version: 0.3.0
Version: 0.4.0
Authors@R: c(person("Dominik", "Rafacz", email = "[email protected]",
role = c("aut", "cre"),
comment = c(ORCID = "0000-0003-0925-1909")),
Expand All @@ -22,24 +22,23 @@ Depends:
R (>= 3.2.0)
Imports:
cranlogs,
ggforce,
ggplot2,
ggraph,
graphlayouts,
httr,
igraph,
jsonlite,
scales
jsonlite
Suggests:
BiocManager,
shiny,
shinycssloaders,
covr,
devtools,
ggplot2,
ggraph,
graphlayouts,
igraph,
knitr,
miniCRAN,
plyr,
rmarkdown,
scales,
shiny,
shinycssloaders,
spelling,
stringi,
testthat (>= 2.1.0),
Expand Down
9 changes: 3 additions & 6 deletions NAMESPACE
Original file line number Diff line number Diff line change
Expand Up @@ -21,17 +21,14 @@ export(get_description)
export(get_downloads)
export(plot_dependencies)
export(plot_downloads)
import(ggplot2)
import(ggraph)
import(igraph)
importFrom(ggforce,geom_circle)
importFrom(graphlayouts,draw_circle)
importFrom(httr,GET)
importFrom(httr,content)
importFrom(scales,comma)
importFrom(stats,quantile)
importFrom(stats,reshape)
importFrom(stats,setNames)
importFrom(stats,time)
importFrom(utils,available.packages)
importFrom(utils,contrib.url)
importFrom(utils,install.packages)
importFrom(utils,menu)
importFrom(utils,packageVersion)
9 changes: 9 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,12 @@
# deepdep 0.4.0
* removed hard dependencies on plotting-related packages; `ggplot2`, `ggraph`, `graphlayouts`, `igraph`, and `scales` are now Suggests instead of Imports (issue #32)
* removed unused dependency on `ggforce`
* added `declutter` parameter for `plot_dependencies()` that allows for ignoring non-strong dependencies of Suggests while plotting (issue #27)
* `vcr` package is now optional for running tests (pull request #26)

# deepdep 0.3.1
* adjusted parameter of `deepdep` function similarly to `get_dependencies` (issue #24)

# deepdep 0.3.0
* adjusted `dependency_type` argument to be consistent with `tools` package (issue #19)
* added `show_stamp` parameter for plot function (issue #20)
Expand Down
183 changes: 93 additions & 90 deletions R/plot_deepdep.R
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@
#' will be displayed below package names. Defaults to \code{FALSE}.
#' @param show_stamp A \code{logical}. If \code{TRUE} (the default) the package version and
#' plot creation time will be added
#' @param declutter A \code{logical}. If \code{TRUE} then all layers beyond the first one
#' ignore non-strong dependencies (i.e. "Suggests" and "Enhances"). This visualizes the
#' so-called "hard costs of weak suggests".
#' @param ... Other arguments passed to the \code{deepdep} function.
#'
#' @return A \code{ggplot2, gg, ggraph, deepdep_plot} class object.
Expand All @@ -39,61 +42,61 @@
#' plot_dependencies("shiny", show_downloads = TRUE)
#' }
#'
#' @importFrom ggforce geom_circle
#' @importFrom graphlayouts draw_circle
#' @importFrom stats quantile reshape
#' @importFrom utils packageVersion
#' @import ggplot2
#' @import ggraph
#' @import igraph
#'
#' @rdname plot_deepdep
#' @export
plot_dependencies <- function(x, type = "circular", same_level = FALSE, reverse = FALSE,
label_percentage = 1, show_version = FALSE, show_downloads = FALSE,
show_stamp = TRUE, ...) {
show_stamp = TRUE, declutter = FALSE, ...) {
UseMethod("plot_dependencies")
}

#' @rdname plot_deepdep
#' @export
plot_dependencies.default <- function(x, type = "circular", same_level = FALSE, reverse = FALSE,
label_percentage = 1, show_version = FALSE, show_downloads = FALSE,
show_stamp = TRUE, ...) {
show_stamp = TRUE, declutter = FALSE, ...) {
stop("This type of object does not have implemented method for 'plot_dependencies'")
}

#' @rdname plot_deepdep
#' @export
plot_dependencies.character <- function(x, type = "circular", same_level = FALSE, reverse = FALSE,
label_percentage = 1, show_version = FALSE, show_downloads = FALSE,
show_stamp = TRUE, ...) {
show_stamp = TRUE, declutter = FALSE, ...) {
package_name <- NULL
if (show_downloads == TRUE || label_percentage < 1)
dd <- deepdep(x, downloads = TRUE, ...)
else dd <- deepdep(x, ...)
plot_dependencies(dd, type, same_level, reverse, label_percentage, show_version, show_downloads, show_stamp)
plot_dependencies(dd, type, same_level, reverse, label_percentage, show_version, show_downloads, show_stamp, declutter)
}

#' @rdname plot_deepdep
#' @export
plot_dependencies.deepdep <- function(x, type = "circular", same_level = FALSE, reverse = FALSE,
label_percentage = 1, show_version = FALSE, show_downloads = FALSE,
show_stamp = TRUE, ...) {
show_stamp = TRUE, declutter = FALSE, ...) {
# Due to NSE inside of the function, we have to declare "labeled" as NULL to prevent check fail
labeled <- NULL
node1.name <- NULL
node2.name <- NULL
name <- NULL


layer <- NULL

# TODO: add boolean returns to check if packages are available
if (!require_packages(c("ggplot2", "ggraph", "igraph", "graphlayouts"),
use_case = "plot package dependencies"))
stop("Missing necessary packages.")

if ((label_percentage < 1 || show_downloads == TRUE) && !("grand_total" %in% colnames(x)))
stop("When you use 'label_percentage' or 'show_downloads'",
" you have to pass deepdep object with 'grand_total' column")

if (nrow(x) == 0) {
G <- make_graph(edges = c(), n = 1)
G <- set_vertex_attr(G, "name", value = attr(x, "package_name"))
G <- igraph::make_graph(edges = c(), n = 1)
G <- igraph::set_vertex_attr(G, "name", value = attr(x, "package_name"))
type <- "tree"
} else {
if (show_version) {
Expand All @@ -102,60 +105,63 @@ plot_dependencies.deepdep <- function(x, type = "circular", same_level = FALSE,
if (show_downloads) {
x <- add_downloads_to_name(x)
}
G <- graph_from_data_frame(x)
if (declutter) {
x <- x[x[["origin"]] == x[[1, "origin"]] |
x[["type"]] %in% match_dependency_type("strong"), ]
}
G <- igraph::graph_from_data_frame(x)
}

G <- add_layers_to_vertices(G, x)
if (!same_level) {
G <- delete_edges_within_layer(G)
}
if (!reverse) {
G <- delete_reverse_edges(G)
}


# mark vertices to label
pkg_downloads <- unlist(x[!duplicated(x[["name"]]), "grand_total"])
# central node should always be labeled
V(G)$labeled <- c(TRUE, pkg_downloads >= quantile(pkg_downloads, probs = 1 - label_percentage))
labels <- levels(factor(E(G)$type))

igraph::V(G)$labeled <- c(TRUE, pkg_downloads >= quantile(pkg_downloads, probs = 1 - label_percentage))
labels <- levels(factor(igraph::E(G)$type))
g <- switch(type,
tree = ggraph(G, "tree") +
theme_void(),
circular = ggraph(graph = G, layout = "focus", focus = 1) +
draw_circle(use = "focus", max.circle = max(V(G)$layer), col = "#252525") +
theme_void() +
coord_fixed())

tree = ggraph::ggraph(G, "tree") +
ggplot2::theme_void(),
circular = ggraph::ggraph(graph = G, layout = "focus", focus = 1) +
graphlayouts::draw_circle(use = "focus", max.circle = max(igraph::V(G)$layer), col = "#252525") +
ggplot2::theme_void() +
ggplot2::coord_fixed())
if (nrow(x) != 0) {
g <- g + geom_edge_link(aes(end_cap = label_rect(node2.name),
start_cap = label_rect(node1.name),
edge_width = type,
edge_linetype = type),
#edge_color = reverse),
arrow = arrow(length = unit(0.5, 'lines'),
ends = "first",
type = "closed",
angle = 16.6),
color = "#1f271b") +
scale_edge_linetype_manual(values = get_edgelinetype_default_scale()) +
scale_edge_width_manual(values = get_edgewidth_default_scale()) +
theme(legend.key.width = unit(3, "lines"))
g <- g + ggraph::geom_edge_link(ggplot2::aes(end_cap = ggraph::label_rect(node2.name),
start_cap = ggraph::label_rect(node1.name),
edge_width = type,
edge_linetype = type),
arrow = ggplot2::arrow(length = ggplot2::unit(0.5, 'lines'),
ends = "first",
type = "closed",
angle = 16.6),
color = "#1f271b") +
ggraph::scale_edge_linetype_manual(values = get_edgelinetype_default_scale()) +
ggraph::scale_edge_width_manual(values = get_edgewidth_default_scale()) +
ggplot2::theme(legend.key.width = ggplot2::unit(3, "lines"))
}

g <- g + geom_node_point(aes(fill = factor(layer)),
size = 3, shape = 21, show.legend = FALSE) +
geom_node_label(data = function(g) g[g[, "labeled"], ],
aes(label = name, fill = factor(layer)),
show.legend = FALSE,
label.padding = unit(0.28, "lines")) +
default_nodefill_scale(length(levels(factor(V(G)$layer))))
g <- g + ggraph::geom_node_point(ggplot2::aes(fill = factor(layer)),
size = 3, shape = 21, show.legend = FALSE) +
ggraph::geom_node_label(data = function(g) g[g[, "labeled"], ],
ggplot2::aes(label = name, fill = factor(layer)),
show.legend = FALSE,
label.padding = ggplot2::unit(0.28, "lines")) +
default_nodefill_scale(length(levels(factor(igraph::V(G)$layer))))
if (show_stamp)
g <- g + labs(caption = paste0("Plot made with deepdep v",
packageVersion("deepdep"),
" on ", format(Sys.time(), usetz = FALSE)))

g <- g + ggplot2::labs(caption = paste0("Plot made with deepdep v",
packageVersion("deepdep"),
" on ", format(Sys.time(), usetz = FALSE)))
class(g) <- c(class(g), "deepdep_plot")
g
}
Expand All @@ -165,7 +171,7 @@ plot_dependencies.deepdep <- function(x, type = "circular", same_level = FALSE,
#'
#' @param G An \code{igraph} object.
add_layers_to_vertices <- function(G, x) {
V(G)$layer <- c(0, x[match(V(G)$name[-1], x$name), "dest_level"])
igraph::V(G)$layer <- c(0, x[match(igraph::V(G)$name[-1], x$name), "dest_level"])
G
}

Expand All @@ -174,32 +180,29 @@ add_layers_to_vertices <- function(G, x) {
#'
#' @param G An \code{igraph} object.
delete_edges_within_layer <- function(G) {
edges_to_delete <- E(G)[
head_of(G, E(G))$layer == tail_of(G, E(G))$layer]
delete_edges(G, edges_to_delete)
edges_to_delete <- igraph::E(G)[
igraph::head_of(G, igraph::E(G))$layer == igraph::tail_of(G, igraph::E(G))$layer
]
igraph::delete_edges(G, edges_to_delete)
}

#' @title Remove edges that points from vertice on lower to higher level
#' @title Remove edges that point from vertices on lower to higher level
#' @noRd
#'
#' @param G An \code{igraph} object.
delete_reverse_edges <- function(G) {
# rev_inds <-
# head_of(G, E(G))$layer < tail_of(G, E(G))$layer
edges_to_delete <- E(G)[
head_of(G, E(G))$layer < tail_of(G, E(G))$layer]
delete_edges(G, edges_to_delete)
# E(G)$reverse <- FALSE
# E(G)$reverse[rev_inds] <- TRUE
# G
edges_to_delete <- igraph::E(G)[
igraph::head_of(G, igraph::E(G))$layer < igraph::tail_of(G, igraph::E(G))$layer
]
igraph::delete_edges(G, edges_to_delete)
}

get_edgewidth_default_scale <- function() {
c(Depends = unit(1, "lines"),
Imports = unit(0.8, "lines"),
Enhances = unit(0.6, "lines"),
Suggests = unit(0.4, "lines"),
LinkingTo = unit(0.4, "lines"))
c(Depends = ggplot2::unit(1, "lines"),
Imports = ggplot2::unit(0.8, "lines"),
Enhances = ggplot2::unit(0.6, "lines"),
Suggests = ggplot2::unit(0.4, "lines"),
LinkingTo = ggplot2::unit(0.4, "lines"))
}

get_edgelinetype_default_scale <- function() {
Expand All @@ -212,28 +215,28 @@ get_edgelinetype_default_scale <- function() {

default_nodefill_scale <- function(num_colors) {
if (num_colors <= 7)
scale_fill_manual(values = c("#5fc8f4",
"#a1ce40",
"#fde74c",
"#ff8330",
"#e55934",
"#7b5e7b",
"#664e4c"))
else scale_fill_discrete()
ggplot2::scale_fill_manual(values = c("#5fc8f4",
"#a1ce40",
"#fde74c",
"#ff8330",
"#e55934",
"#7b5e7b",
"#664e4c"))
else ggplot2::scale_fill_discrete()
}

add_version_to_name <- function(x) {
tmp <- x[!duplicated(x$name), c("name", "version")]
nv <- ifelse(is.na(tmp$version), tmp$name, paste0(tmp$name, "\n(", tmp$version, ")"))
names(nv) <- tmp$name
x$name <- nv[x$name]
x
tmp <- x[!duplicated(x$name), c("name", "version")]
nv <- ifelse(is.na(tmp$version), tmp$name, paste0(tmp$name, "\n(", tmp$version, ")"))
names(nv) <- tmp$name
x$name <- nv[x$name]
x
}

add_downloads_to_name <- function(x) {
tmp <- x[!duplicated(x$name), c("name", "grand_total")]
nv <- ifelse(is.na(tmp$grand_total), tmp$name, paste0(tmp$name, "\n", tmp$grand_total))
names(nv) <- tmp$name
x$name <- nv[x$name]
x
tmp <- x[!duplicated(x$name), c("name", "grand_total")]
nv <- ifelse(is.na(tmp$grand_total), tmp$name, paste0(tmp$name, "\n", tmp$grand_total))
names(nv) <- tmp$name
x$name <- nv[x$name]
x
}
Loading

0 comments on commit fe999ad

Please sign in to comment.