diff --git a/DESCRIPTION b/DESCRIPTION index 8170de3..05398f5 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -34,11 +34,10 @@ Suggests: rmarkdown, rnaturalearthdata, spelling -RoxygenNote: 7.2.3 +RoxygenNote: 7.3.0 Collate: 'classes.R' 'accessors.R' - 'auxil.R' 'basicMethods.R' 'buffer.R' 'closestNode.R' @@ -49,10 +48,13 @@ Collate: 'dropDead.R' 'extractFromLayer.R' 'findLand.R' + 'geo.segments.R' 'geograph.R' 'globals.R' + 'hasCosts.R' 'interact.R' 'isInArea.R' + 'keepMaxConnected.R' 'makeGrid.R' 'plot.R' 'rebuild.R' diff --git a/NAMESPACE b/NAMESPACE index c9a3411..8c63a52 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -2,7 +2,6 @@ S3method(plot,gPath) export("%>%") -export() export(.gData.valid) export(.gGraph.valid) export(.zoomlog.up) @@ -42,6 +41,7 @@ export(is.gData) export(is.gGraph) export(isInArea) export(isReachable) +export(keepMaxConnectedSet) export(makeGrid) export(plotEdges) export(setCosts) diff --git a/R/connectivity.R b/R/connectivity.R index 5faccb5..7f6e24d 100644 --- a/R/connectivity.R +++ b/R/connectivity.R @@ -162,6 +162,25 @@ setMethod("isConnected", "gData", function(object, ...) { }) # end isConnected for gData +## the GENERIC of this method is given in package 'graph' +#' @rdname connectivity +#' @export +setMethod("isConnected", "gGraph", function(object, ...) { + ## checks ## + if (!is.gGraph(object)) stop("'object' is not a valid gData object.") + + ## set args for areConnected ## + myNodes <- getNodes(object) + ## wrapper ## + res <- areConnected(object, myNodes) + + ## return res ## + return(res) +}) # end isConnected for gGraph + + + + diff --git a/R/dijkstra.R b/R/dijkstra.R index db59eb6..8eac55c 100644 --- a/R/dijkstra.R +++ b/R/dijkstra.R @@ -163,51 +163,58 @@ setMethod("dijkstraBetween", "gGraph", function(x, from, to) { #' @rdname dijkstra-methods #' @export setMethod("dijkstraBetween", "gData", function(x) { - ## temp <- function(x){ # for debugging + # we transform the gData object to gGraph, extracting the nodes from the gData object. + # The node ids are found in the @nodes.id of the gData object: in this case we + # can call getNodes(). + # Then simply pass the new gGraph object to the method for gGraph. ## some checks ## if (!require(RBGL)) stop("RBGL is required.") if (!is.gData(x)) stop("x is not a valid gData object") if (!exists(x@gGraph.name, envir = .GlobalEnv)) stop(paste("gGraph object", x@gGraph.name, "not found.")) if (length(x@nodes.id) == 0) stop("No assigned nodes (x@nodes.id is empty).") - if (!isConnected(x)) stop("Not all locations are connected by the graph.") + # if (!isConnected(x)) stop("Not all locations are connected by the graph.") ## build the wrapper ## + # @TODO check labels to keep myGraph <- get(x@gGraph.name, envir = .GlobalEnv) - coords <- getCoords(myGraph) # store xy coords for later - myGraph <- getGraph(myGraph) # don't do this before getCoords - - ## build indices of all pairwise combinations ## - pairIdStart <- integer() - pairIdStop <- integer() - - for (i in 1:(length(getNodes(x)) + 1)) { - j <- i - while ((j <- j + 1) < length(getNodes(x)) + 1) { - pairIdStart <- c(pairIdStart, i) - pairIdStop <- c(pairIdStop, j) - } - } - - ## wrap ## - ## ! sp.between does not return duplicated paths - res <- RBGL::sp.between(myGraph, start = x@nodes.id[pairIdStart], finish = x@nodes.id[pairIdStop]) - - - ## handle duplicated paths ## - if (length(res) < length(pairIdStart)) { # res should have length = pairIdStart - fromTo <- paste(x@nodes.id[pairIdStart], x@nodes.id[pairIdStop], sep = ":") # all different paths - res <- res[fromTo] - } - - - ## make it a class "gPath" (output + xy coords) ## - allNodes <- unique(unlist(lapply(res, function(e) e$path_detail))) - ## res$xy <- getCoords(x)[allNodes,] - attr(res, "xy") <- coords[allNodes, ] - class(res) <- "gPath" - - return(res) + myNodes <- getNodes(x) + dijkstraBetween(myGraph,from=myNodes, to=myNodes) + # + # coords <- getCoords(myGraph) # store xy coords for later + # myGraph <- getGraph(myGraph) # don't do this before getCoords + # + # ## build indices of all pairwise combinations ## + # pairIdStart <- integer() + # pairIdStop <- integer() + # + # for (i in 1:(length(getNodes(x)) + 1)) { + # j <- i + # while ((j <- j + 1) < length(getNodes(x)) + 1) { + # pairIdStart <- c(pairIdStart, i) + # pairIdStop <- c(pairIdStop, j) + # } + # } + # + # ## wrap ## + # ## ! sp.between does not return duplicated paths + # res <- RBGL::sp.between(myGraph, start = x@nodes.id[pairIdStart], finish = x@nodes.id[pairIdStop]) + # + # + # ## handle duplicated paths ## + # if (length(res) < length(pairIdStart)) { # res should have length = pairIdStart + # fromTo <- paste(x@nodes.id[pairIdStart], x@nodes.id[pairIdStop], sep = ":") # all different paths + # res <- res[fromTo] + # } + # + # + # ## make it a class "gPath" (output + xy coords) ## + # allNodes <- unique(unlist(lapply(res, function(e) e$path_detail))) + # ## res$xy <- getCoords(x)[allNodes,] + # attr(res, "xy") <- coords[allNodes, ] + # class(res) <- "gPath" + # + # return(res) }) # end dijkstraBetween for gData @@ -249,21 +256,24 @@ setMethod("dijkstraFrom", "gGraph", function(x, start) { if (!all(start %in% getNodes(x))) stop("Starting node is not in x.") ## check connectivity ## - if (!areConnected(x, getNodes(myGraph))) stop("Not all nodes are connected by the graph.") - + if (!areConnected(x, getNodes(x))) stop("Not all nodes are connected by the graph.") + ## build the wrapper ## myGraph <- getGraph(x) ## if(is.character(costs) && costs=="default"){ ## costs <- unlist(edgeWeights(myGraph)) + endNodes <- getNodes(x)[!getNodes(x) %in% start] ## } - +#browser() ## wrap ## - res <- RBGL::dijkstra.sp(myGraph, start = start) + #res <- RBGL::dijkstra.sp(myGraph, start = start) + res <- RBGL::sp.between(myGraph, start = start, + finish = endNodes) ## sp.between uses unique(x@nodes.id) ## ## eventually have to duplicate paths ## temp <- gsub(".*:", "", names(res)) - res <- res[match(getNodes(x), temp)] + res <- res[match(endNodes, temp)] ## make it a class "gPath" (output + xy coords) ## diff --git a/R/auxil.R b/R/geo.segments.R similarity index 67% rename from R/auxil.R rename to R/geo.segments.R index b9d2e3c..ba5a807 100644 --- a/R/auxil.R +++ b/R/geo.segments.R @@ -1,21 +1,16 @@ -#' Auxiliary methods for geoGraph -#' -#' These methods are low-level functions called by other procedures of -#' \code{geoGraph}. Some can, however, be useful in themselves. Note that -#' unlike other functions in \code{geoGraph}, these functions do not generally -#' test for the validity of the provided arguments (for speed purposes).\cr -#' -#' - \code{hasCosts}: tests whether a \linkS4class{gGraph} has costs associated -#' to its edges.\cr -#' -#' - \code{geo.segments}: a substitute to \code{segments} which correctly draws -#' segments between locations distant by more than 90 degrees of longitude.\cr -#' -#' - \code{rebuild}: in development. +#' Plot segments correctly when crossing the antimeridian #' +#' A substitute to \code{segments} which correctly draws +#' segments between locations distant by more than 90 degrees of longitude +#' (i.e. from one hemisphere to the other). It is used instead of segments, but +#' it is slower. +#' +#' This low-level function is designed to be called by other procedures of +#' [geoGraph]. However, it can sometimes be useful by itself. Note that +#' unlike other functions in \code{geoGraph}, this functions does not +#' test for the validity of the provided arguments (for speed purposes). #' #' @aliases hasCosts rebuild geo.segments -#' @param x a valid \linkS4class{gGraph}. #' @param x0,y0 coordinates of points *from* which to draw. #' @param x1,y1 coordinates of points *to* which to draw. #' @param col a character string or an integer indicating the color of the @@ -24,52 +19,10 @@ #' @param lwd an integer indicating the line width. #' @param \dots further graphical parameters (from 'par') passed to the #' \code{segments} function. -#' @return For \code{hasCost}, a logical value is returned. \code{geo.segments} -#' returns NULL. - +#' @return NULL. +#' #' @keywords utilities methods #' @name auxiliary -#' @examples -#' -#' hasCosts(worldgraph.10k) -#' -NULL - - - -############## -## hasCosts -############## -#' @rdname auxiliary -#' @export - -hasCosts <- function(x) { - if (length(getGraph(x)@edgeData@data) == 0) { - return(FALSE) - } - w <- getCosts(x, res.type = "vector") - if (length(unique(w)) < 2) { - return(FALSE) - } - return(TRUE) -} - - - - - - -################### -## geo.segments -################### -## -## Rectifies segments drawn from one hemisphere to another -## in the wrong direction (i.e. not the shortest path) -## and draws it. -## -## Is to be called instead segments but will be slower. -## -#' @rdname auxiliary #' @export geo.segments <- function(x0, y0, x1, y1, @@ -78,39 +31,39 @@ geo.segments <- function(x0, y0, x1, y1, THRES <- 90 XMIN <- graphics::par("usr")[1] XMAX <- graphics::par("usr")[2] - + ## pin down problematic segments ## toChange <- abs(x0 - x1) > THRES if (sum(toChange) == 0) { # exit here if everything is ok. graphics::segments(x0, y0, x1, y1, - col = col, lty = lty, lwd = lwd, ... + col = col, lty = lty, lwd = lwd, ... ) return(invisible()) } - + ## isolate problematic segments ## x0.ok <- x0[!toChange] # these are ok x1.ok <- x1[!toChange] y0.ok <- y0[!toChange] y1.ok <- y1[!toChange] - + x0 <- x0[toChange] # problematic x1 <- x1[toChange] y0 <- y0[toChange] y1 <- y1[toChange] - - + + ## sort x and y coordinates so that x0 < x1 ## toInvert <- (x0 > x1) temp <- x0[toInvert] # x coords x0[toInvert] <- x1[toInvert] x1[toInvert] <- temp - + temp <- y0[toInvert] # y coords y0[toInvert] <- y1[toInvert] y1[toInvert] <- temp - - + + ## define new segments ## ## notations: ## - x0: x coord, left point @@ -121,14 +74,14 @@ geo.segments <- function(x0, y0, x1, y1, ## - h0, h1: differential of y coord for new coord ## (h0/d0 = h1/d1) ## - H: distance between y0 and y1 - - + + d0 <- x0 - XMIN d1 <- XMAX - x1 H <- abs(y1 - y0) h0 <- H * (d0 / d1) / (1 + (d0 / d1)) h1 <- H - h0 - + x0.new <- rep(XMIN, length(x0)) x1.new <- rep(XMAX, length(x1)) ## for y coords, h0 (resp. h1) can be added or subtracted, depending on yo < y1 @@ -137,11 +90,11 @@ geo.segments <- function(x0, y0, x1, y1, facMod.1 <- facMod.0 * -1 h0 <- h0 * facMod.0 h1 <- h1 * facMod.1 - + y0.new <- y0 + h0 y1.new <- y1 + h1 - - + + ## add new segments to old segments ## ## order: old segments, new segments ## new segments: x0=original coords @@ -150,21 +103,21 @@ geo.segments <- function(x0, y0, x1, y1, y0.out <- c(y0, y1) x1.out <- c(x0.new, x1.new) y1.out <- c(y0.new, y1.new) - - + + ## final call to segments ## ## non-modified segments oxpd <- graphics::par("xpd") graphics::par(xpd = TRUE) graphics::segments(x0.ok, y0.ok, x1.ok, y1.ok, - col = col, lty = lty, lwd = lwd, ... + col = col, lty = lty, lwd = lwd, ... ) - + ## modified segments graphics::segments(x0.out, y0.out, x1.out, y1.out, - col = col, lty = 3, lwd = lwd, ... + col = col, lty = 3, lwd = lwd, ... ) - + graphics::par(xpd = oxpd) return(invisible()) } # end geo.segments diff --git a/R/hasCosts.R b/R/hasCosts.R new file mode 100644 index 0000000..f3eaa1e --- /dev/null +++ b/R/hasCosts.R @@ -0,0 +1,35 @@ +#' Check if a gGraph has costs +#' +#' This function tests whether a \linkS4class{gGraph} has costs associated +#' to its edges. +#' +#' This low-level function is designed to be called by other procedures of +#' [geoGraph]. However, it can sometimes be useful by itself. Note that +#' unlike other functions in \code{geoGraph}, this functions does not +#' test for the validity of the provided arguments (for speed purposes). +#' +#' @param x a valid \linkS4class{gGraph}. +#' @return a logical value is returned. +#' @keywords utilities methods +#' @name auxiliary +#' @examples +#' +#' hasCosts(worldgraph.10k) +#' +#' @export + +hasCosts <- function(x) { + if (length(getGraph(x)@edgeData@data) == 0) { + return(FALSE) + } + w <- getCosts(x, res.type = "vector") + if (length(unique(w)) < 2) { + return(FALSE) + } + return(TRUE) +} + + + + + diff --git a/R/keepMaxConnected.R b/R/keepMaxConnected.R new file mode 100644 index 0000000..159cf87 --- /dev/null +++ b/R/keepMaxConnected.R @@ -0,0 +1,48 @@ +#' Keep only the largest connected set +#' +#' This function removes all nodes that are not part of the largest connected set. +#' +#' @param x a [gGraph] object +#' @returns a [gGraph] object with only the nodes from the largest set remaining +#' @examples +#' max_set <- keepMaxConnectedSet(worldgraph.10k) +#' plot(max_set) +#' +#' @export + +keepMaxConnectedSet <- function (x){ + myGraph <- getGraph(x) + connected_sets <- RBGL::connectedComp(myGraph) + # find the largest set + max_set <- connected_sets[[which.max(lapply(connected_sets, length))]] + max_set <- as.numeric(max_set) + # all cells NOT in the largest set need to be removed + + # get the edges from the graph + edgeW <- edgeWeights(myGraph) + edgeL <- edgeL(myGraph) + + # We create a new list and then copy over only the edges for which we have a node + # from the largest set + newEdgeL <- list() + for (i in 1:length(edgeL)) { + newEdgeL[[i]] <- list() + # if the source is in the set, we keep its edges but remove any destination not in the set + if (i %in% max_set){ + newEdgeL[[i]]$edges <- edgeL[[i]]$edges[edgeL[[i]]$edges %in% max_set] + newEdgeL[[i]]$weights <- edgeW[[i]][edgeL[[i]]$edges %in% max_set] + } else { #we remove this edge + newEdgeL[[i]]$edges <- numeric(0) + newEdgeL[[i]]$weights <- numeric(0) + } + } + names(newEdgeL) <- nodes(myGraph) # items of the list must be named + + newGraph <- new("graphNEL", nodes = nodes(myGraph), edgeL = newEdgeL) + res <- x + res@graph <- newGraph + + res <- dropDeadNodes(res) + + return(res) +} diff --git a/data-raw/temp/drop_nodes_speed.R b/data-raw/temp/drop_nodes_speed.R new file mode 100644 index 0000000..c8e0e7f --- /dev/null +++ b/data-raw/temp/drop_nodes_speed.R @@ -0,0 +1,68 @@ +library(geoGraph) +library(tictoc) +devtools::load_all() + +x<-worldgraph.40k +myGraph <- getGraph(x) +connected_sets <- RBGL::connectedComp(myGraph) +# find the largest set +max_set <- connected_sets[[which.max(lapply(connected_sets, length))]] +max_set <- as.numeric(max_set) +# all cells NOT in the largest set need to be removed + +# get the edges from the graph +edgeW <- edgeWeights(myGraph) +edgeL <- edgeL(myGraph) + +tic() +# We create a new list and then copy over only the edges for which we have a node +# from the largest set +newEdgeL <- list() +for (i in 1:length(edgeL)) { + newEdgeL[[i]] <- list() + # if the source is in the set, we keep its edges but remove any destination not in the set + if (i %in% max_set){ + newEdgeL[[i]]$edges <- edgeL[[i]]$edges[edgeL[[i]]$edges %in% max_set] + newEdgeL[[i]]$weights <- edgeW[[i]][edgeL[[i]]$edges %in% max_set] + } else { #we remove this edge + newEdgeL[[i]]$edges <- numeric(0) + newEdgeL[[i]]$weights <- numeric(0) + } +} +toc() +# 6.974 secs + +## use an apply function to loop over all elements +max_set +keep_selected_nodes <-function(i, edgeL, max_set){ + this_edge <- list() + # if the source is in the set, we keep its edges but remove any destination not in the set + if (i %in% max_set){ + this_edge$edges <- edgeL[[i]]$edges[edgeL[[i]]$edges %in% max_set] + this_edge$weights <- edgeW[[i]][edgeL[[i]]$edges %in% max_set] + } else { #we remove this edge + this_edge$edges <- numeric(0) + this_edge$weights <- numeric(0) + } + this_edge +} +tic() +newEdgeL2<-lapply(1:length(edgeL),FUN=keep_selected_nodes,edgeL=edgeL,max_set=max_set) +toc() +identical(newEdgeL,newEdgeL2) + + +## break down in two steps # not working yet???? +tic() +newEdgeL3 <-lapply(1:length(edgeL),FUN=function(i) {list(edges=numeric(0), weights=numeric(0))}) +for (i in max_set) { + newEdgeL3[[i]] <- list() + # if the source is in the set, we keep its edges but remove any destination not in the set + newEdgeL3[[i]]$edges <- edgeL[[i]]$edges[edgeL[[i]]$edges %in% max_set] + newEdgeL3[[i]]$weights <- edgeW[[i]][edgeL[[i]]$edges %in% max_set] +} +toc() +identical(newEdgeL,newEdgeL3) + + +## diff --git a/man/auxiliary.Rd b/man/auxiliary.Rd index 329fba0..49dadbb 100644 --- a/man/auxiliary.Rd +++ b/man/auxiliary.Rd @@ -1,14 +1,12 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/auxil.R +% Please edit documentation in R/geo.segments.R, R/hasCosts.R \name{auxiliary} \alias{auxiliary} +\alias{geo.segments} \alias{hasCosts} \alias{rebuild} -\alias{geo.segments} -\title{Auxiliary methods for geoGraph} +\title{Plot segments correctly when crossing the antimeridian} \usage{ -hasCosts(x) - geo.segments( x0, y0, @@ -19,10 +17,10 @@ geo.segments( lwd = graphics::par("lwd"), ... ) + +hasCosts(x) } \arguments{ -\item{x}{a valid \linkS4class{gGraph}.} - \item{x0, y0}{coordinates of points \emph{from} which to draw.} \item{x1, y1}{coordinates of points \emph{to} which to draw.} @@ -36,25 +34,33 @@ segments.} \item{\dots}{further graphical parameters (from 'par') passed to the \code{segments} function.} + +\item{x}{a valid \linkS4class{gGraph}.} } \value{ -For \code{hasCost}, a logical value is returned. \code{geo.segments} -returns NULL. +NULL. + +a logical value is returned. } \description{ -These methods are low-level functions called by other procedures of -\code{geoGraph}. Some can, however, be useful in themselves. Note that -unlike other functions in \code{geoGraph}, these functions do not generally -test for the validity of the provided arguments (for speed purposes).\cr +A substitute to \code{segments} which correctly draws +segments between locations distant by more than 90 degrees of longitude +(i.e. from one hemisphere to the other). It is used instead of segments, but +it is slower. + +This function tests whether a \linkS4class{gGraph} has costs associated +to its edges. } \details{ -\itemize{ -\item \code{hasCosts}: tests whether a \linkS4class{gGraph} has costs associated -to its edges.\cr -\item \code{geo.segments}: a substitute to \code{segments} which correctly draws -segments between locations distant by more than 90 degrees of longitude.\cr -\item \code{rebuild}: in development. -} +This low-level function is designed to be called by other procedures of +\link{geoGraph}. However, it can sometimes be useful by itself. Note that +unlike other functions in \code{geoGraph}, this functions does not +test for the validity of the provided arguments (for speed purposes). + +This low-level function is designed to be called by other procedures of +\link{geoGraph}. However, it can sometimes be useful by itself. Note that +unlike other functions in \code{geoGraph}, this functions does not +test for the validity of the provided arguments (for speed purposes). } \examples{ diff --git a/man/connectivity.Rd b/man/connectivity.Rd index f3d53c8..56b207e 100644 --- a/man/connectivity.Rd +++ b/man/connectivity.Rd @@ -10,6 +10,7 @@ \alias{connectivityPlot-methods} \alias{connectivityPlot,gGraph-method} \alias{connectivityPlot,gData-method} +\alias{isConnected,gGraph-method} \title{Check connectivity of a gGraph object} \usage{ areNeighbours(V1, V2, graph) @@ -18,6 +19,8 @@ areConnected(x, nodes) \S4method{isConnected}{gData}(object, ...) +\S4method{isConnected}{gGraph}(object, ...) + isReachable(x, loc) connectivityPlot(x, ...) diff --git a/man/geoGraph-package.Rd b/man/geoGraph-package.Rd index 14a5e4c..cf2a014 100644 --- a/man/geoGraph-package.Rd +++ b/man/geoGraph-package.Rd @@ -113,6 +113,24 @@ x <- dropDeadEdges(x) plot(x, edges = TRUE) title("after droping edges with null weight") +} +\seealso{ +Useful links: +\itemize{ + \item \url{https://github.com/EvolEcolGroup/geograph} + \item \url{https://evolecolgroup.github.io/geograph/} + \item Report bugs at \url{https://github.com/EvolEcolGroup/geograph/issues} +} + +} +\author{ +\strong{Maintainer}: Andrea Manica \email{am315@cam.ac.uk} + +Authors: +\itemize{ + \item Thibaut Jombart +} + } \keyword{manip} \keyword{spatial} diff --git a/man/keepMaxConnectedSet.Rd b/man/keepMaxConnectedSet.Rd new file mode 100644 index 0000000..1bda4e6 --- /dev/null +++ b/man/keepMaxConnectedSet.Rd @@ -0,0 +1,22 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/keepMaxConnected.R +\name{keepMaxConnectedSet} +\alias{keepMaxConnectedSet} +\title{Keep only the largest connected set} +\usage{ +keepMaxConnectedSet(x) +} +\arguments{ +\item{x}{a \link{gGraph} object} +} +\value{ +a \link{gGraph} object with only the nodes from the largest set remaining +} +\description{ +This function removes all nodes that are not part of the largest connected set. +} +\examples{ +max_set <- keepMaxConnectedSet(worldgraph.10k) +plot(max_set) + +} diff --git a/tests/testthat/test_dijkstra.R b/tests/testthat/test_dijkstra.R new file mode 100644 index 0000000..d42dbee --- /dev/null +++ b/tests/testthat/test_dijkstra.R @@ -0,0 +1,66 @@ +test_that("dijkstra_between computes distances correctly", + { + # test the gData method + # we take four locations from 4 different continents: + # "AMERICA", "EUROPE", "CENTRAL_SOUTH_ASIA", "AFRICA" + hgdp_sub <- hgdp[c(24,1,13,27),] + hgdp_between <- dijkstraBetween(hgdp_sub) + # plot(worldgraph.40k, pch = "") + # points(hgdp_sub, lwd = 3) + # plot(hgdp_between) + dist_matrix <- gPath2dist(hgdp_between) + # expect distance between South America and any other location to be + # to be larger than any other distance + expect_true(min(dist_matrix[1:3])>max(dist_matrix[4:6])) + + #now test the same for the gGraph algorithm + # we extract the nodes from the gData object + graph_between <- dijkstraBetween(worldgraph.40k, + from = hgdp_sub@nodes.id, + to = hgdp_sub@nodes.id) + graph_dist_matrix <- gPath2dist(graph_between) + expect_true(identical(dist_matrix, graph_dist_matrix)) + }) + + +testthat::test_that("DijkstraFrom works on a connected graph",{ + + max_set <- keepMaxConnectedSet(worldgraph.10k) + isConnected(max_set) + + #Choose a start point within the graph space + coords_max_set <- getCoords(max_set) + head(coords_max_set) + #node 67 + origin <- "67" + foo<-dijkstraFrom(max_set,origin) + + #Check output is a gPath + testthat::expect_true(inherits(foo,"gPath")) + + #Check resulting gPath 'foo' has the same number of rows as coords_max_set + #(-1 as no path is calculated from origin to origin) + testthat::expect_equal(length(names(foo)),nrow(coords_max_set)-1) + +}) + +testthat::test_that("DijkstraFrom works on a gData object", { + + #Create a subset of hgdp data + hgdp_sub <- hgdp[c(1,2,3,4)] + + #Choose an origin node + start <- "24988" + + myPath <- dijkstraFrom(hgdp_sub, start) + + #Check output is a gPath + testthat::expect_true(inherits(myPath,"gPath")) + + #Check that myPath has the expected pairs of nodes + testthat::expect_equal(names(myPath), c("24988:26898", "24988:11652", "24988:22532", "24988:23709")) + +}) + + + diff --git a/tests/testthat/test_keepMaxConnectedSet.R b/tests/testthat/test_keepMaxConnectedSet.R new file mode 100644 index 0000000..61b8ce2 --- /dev/null +++ b/tests/testthat/test_keepMaxConnectedSet.R @@ -0,0 +1,13 @@ +test_that("keepMaxConnectedSet drops all small sets", + { + # we start with worldgraph.10k, where Eurasia and Africa form the biggest set + # check that the graph is not all connected + expect_false(isConnected(worldgraph.10k)) + max_set <- keepMaxConnectedSet(worldgraph.10k) + # the max set should be all connected + expect_true(isConnected(max_set)) + # check that the max set does not include the Americas + coords_max_set <- getCoords(max_set) + expect_true(sum(coords_max_set[,1]< -20)==0) + }) + \ No newline at end of file