From 207b858f2ec814aab7384ce2902f488325a8584c Mon Sep 17 00:00:00 2001 From: Adrian Waddell Date: Mon, 25 Jun 2012 00:00:00 +0000 Subject: [PATCH] version 0.1.4 --- DESCRIPTION | 8 +- MD5 | 10 +- NAMESPACE | 2 +- NEWS | 6 + R/ng_graph.R | 835 +++++++++++++++++++++-------------------- inst/doc/RnavGraph.pdf | Bin 845408 -> 845517 bytes 6 files changed, 435 insertions(+), 426 deletions(-) diff --git a/DESCRIPTION b/DESCRIPTION index d9d7278..80692c5 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,8 +1,8 @@ Package: RnavGraph Type: Package Title: Using graphs as a navigational infrastructure. -Version: 0.1.3 -Date: 2012-04-16 +Version: 0.1.4 +Date: 2012-06-25 Author: Adrian R. Waddell and R. Wayne Oldford Maintainer: Adrian Waddell Url: http://www.navgraph.com @@ -20,6 +20,6 @@ Collate: 'AllGenerics.R' 'ng_data.R' 'ng_graph.R' 'ng_path.R' 'Viz2D_Ggobi.R' 'Viz2D_Axis.R' 'Viz2D_tk2d.R' 'FunctionNavGraph.R' 'graphtools.R' 'navGraph.R' 'scagNav.R' 'zzz.R' -Packaged: 2012-04-22 22:08:02 UTC; adrian +Packaged: 2012-06-26 15:12:51 UTC; adrian Repository: CRAN -Date/Publication: 2012-04-23 05:50:58 +Date/Publication: 2012-06-26 15:37:52 diff --git a/MD5 b/MD5 index 92612ee..3cf52bb 100644 --- a/MD5 +++ b/MD5 @@ -1,6 +1,6 @@ -3673d9d195109d07e3b01eaa77b502b3 *DESCRIPTION -c2013f30dbf0baba1aaccacd9a1f38d5 *NAMESPACE -5b6dd643e175d892e1b82c7801aaad86 *NEWS +f037f8689143cd9ea34229b3c8d7a827 *DESCRIPTION +5b39e9968c18a7b751e916a7b03c74e8 *NAMESPACE +1e3ace04f95721594b2da8d30d2ba947 *NEWS 2eb21102bd24f42a9eaa379c87aa36e3 *R/AllGenerics.R 1eae90f5511b1e0227466cecb11e61a3 *R/FunctionNavGraph.R 698183f7c8d7f656c8bda9b23251958c *R/GraphDisplay.R @@ -14,7 +14,7 @@ c023105f8b05388c4f44f5e8c119075b *R/Viz2D_Axis.R 61f8b9c6b01a6ebe5c5c0da86e9fbd37 *R/graphtools.R f0ec55cb22b91af3918f70c881e7bac1 *R/navGraph.R e2046071e11a654375f749ae3f73a299 *R/ng_data.R -341f0517b37a67c8a4f3a8f23e910459 *R/ng_graph.R +1e76a8f29b2bc71a8f7939479d81b2ea *R/ng_graph.R b329d41fa64771577a44a16fadf604a7 *R/ng_image.R a99f1c3a3c7c5bab62790b432ad4e06c *R/ng_path.R 2df6ec796522c5881afa798e4091d435 *R/scagNav.R @@ -37,7 +37,7 @@ e6195073c4c1053f62f75299ab46dc34 *demo/ng_2d_myplot_grid.R 893374fbe4c8212a0239feb08c2cdaaa *demo/ng_2d_scagnostics_olive.R ff1cda694de51a83619676e3aca1c099 *demo/ng_own_viz.R 0a75373364cfcf4acae0aa67e48c3533 *inst/doc/RnavGraph.Rnw -2d8fce94c6d4f91b52d024f833d9a8b2 *inst/doc/RnavGraph.pdf +f0de3a26602f3fc3fcaaa5b03547e2da *inst/doc/RnavGraph.pdf b32561c5cecdc451ee9a893f3efecd4b *inst/tcl/GraphDisplay.tcl ffbe67dcab0a0c7cf371524ffcba5a4d *inst/tcl/tkScatterplotV1.tcl 94bfc13ab09e12cfb4bbc2b23e0f4c05 *inst/tcl/tkScatterplotV3.tcl diff --git a/NAMESPACE b/NAMESPACE index 59b81ff..3022bc5 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -3,7 +3,7 @@ import(tcltk) ## import all functionality import(graph) importFrom(graphics,plot) import(methods) -importFrom(RBGL,kamadaKawaiSpringLayout,fruchtermanReingoldForceDirectedLayout) +##importFrom(RBGL,kamadaKawaiSpringLayout,fruchtermanReingoldForceDirectedLayout) ## exports export( diff --git a/NEWS b/NEWS index 6c5ab5a..84cfb7e 100644 --- a/NEWS +++ b/NEWS @@ -1,3 +1,9 @@ +July 2012, Version 0.1.4 +------------------------ +* RBGL 1.32.1 temporarily sacrifieced layout.cpp, hence + kamadaKawaiSpring and fruchtermanReingold layouts + currently not working + New to Version 0.1.3 -------------------- * fixed .onLoad and .onAttach diff --git a/R/ng_graph.R b/R/ng_graph.R index 1085cd1..624545b 100644 --- a/R/ng_graph.R +++ b/R/ng_graph.R @@ -1,33 +1,33 @@ setClass( - Class = "NG_graph", - representation = representation( - name = "character", - graph = "graph", - xNodes = "numeric", - yNodes = "numeric", - xLabels = "numeric", - yLabels = "numeric", - bbox = "numeric", - layout = "character", - border = "numeric", - sep = 'character' - ), - validity = function(object){ - goThrough <- TRUE - - if(is(object@graph,'graph') == FALSE){ - cat('[NG_graph:validation] graph is not from class graph.\n') - goThrough <- FALSE - } - - if( !all(numNodes(object@graph) == c(length(object@xNodes),length(object@yNodes), - length(object@xLabels), length(object@yLabels), length(object@xNodes)))){ - cat('[NG_graph:validation] dimension of a node related slot is wrong.\n') - goThrough <- FALSE - } - - return(goThrough) - }) + Class = "NG_graph", + representation = representation( + name = "character", + graph = "graph", + xNodes = "numeric", + yNodes = "numeric", + xLabels = "numeric", + yLabels = "numeric", + bbox = "numeric", + layout = "character", + border = "numeric", + sep = 'character' + ), + validity = function(object){ + goThrough <- TRUE + + if(is(object@graph,'graph') == FALSE){ + cat('[NG_graph:validation] graph is not from class graph.\n') + goThrough <- FALSE + } + + if( !all(numNodes(object@graph) == c(length(object@xNodes),length(object@yNodes), + length(object@xLabels), length(object@yLabels), length(object@xNodes)))){ + cat('[NG_graph:validation] dimension of a node related slot is wrong.\n') + goThrough <- FALSE + } + + return(goThrough) + }) @@ -35,280 +35,283 @@ setClass( setMethod( - f = "show", - signature = "NG_graph", - definition = function(object){ - cat("NG_graph object from ng_graph()\n") - cat(paste("name:", object@name,"\n")) - cat(paste("layout:", object@layout,"\n")) - }) + f = "show", + signature = "NG_graph", + definition = function(object){ + cat("NG_graph object from ng_graph()\n") + cat(paste("name:", object@name,"\n")) + cat(paste("layout:", object@layout,"\n")) + }) ## layouting function setMethod( - f = "graphLayout", - signature = "NG_graph", - definition = function(graph,type,...){ - args <- list(...) - - ## ldist stands for label distance (from node) - - ## Distance from the Node Labels to the Node - if(is(args$settings,"NG_Settings")){ - labelDistR <- args$settings@interaction@labelDistRadius - }else if(is.null(args$ldist) == FALSE){ - labelDistR <- args$ldist - }else{ - labelDistR <- 25 - } - - ## circle layout - if(type == 'circle'){ - p <- numNodes(graph@graph) - angle <- seq(0,2*pi, length=p+1)[1:p] - - ## radius of circle for nodes - r <- (min(graph@bbox) - 2*labelDistR - 2*graph@border)/2 - graph@xNodes <- cos(angle)*r + graph@bbox[1]/2 - graph@yNodes <- sin(angle)*r + graph@bbox[2]/2 - - ## radius of circle for label names - - #graph <- updateLabels(graph, ldist=labelDistR, orientation = 'center') - - r <- (min(graph@bbox) - 2*graph@border)/2 - graph@xLabels <- cos(angle)*r + graph@bbox[1]/2 - graph@yLabels <- sin(angle)*r + graph@bbox[2]/2 - - - - } - ## Depend on Rgraphviz -# else if(any(type == c('neato','dot','twopi'))){ -# -# ## agopen is from the Rgraphviz library -# vv <- agopen(graph = graph@graph, name = graph@name, -# layout = type) -# -# x <- sapply(vv@AgNode,function(x)x@center@x) -# y <- sapply(vv@AgNode,function(x)x@center@y) -# nodeNames <- sapply(vv@AgNode,function(x)x@txtLabel@labelText) -# -# if(any(nodeNames != nodes(graph@graph))){ -# stop("[NG_graph:grahLayout] order of nodes after Layouting not the same anymore.\n") -# } -# -# -# ## rescale graph -# graph@xNodes <- (x-min(x))/(diff(range(x))) * -# (graph@bbox[1]- 2*graph@border - 2*labelDistR)+graph@border+labelDistR -# graph@yNodes <- (y-min(y))/(diff(range(y))) * -# (graph@bbox[2]- 2*graph@border - 2*labelDistR)+graph@border+labelDistR -# -# graph <- updateLabels(graph, ldist=labelDistR, orientation = 'center') -# -# -# } - else if(type == 'random'){ - - - lay <- randomGraphLayout(graph@graph) - - if(all(colnames(lay) == nodes(graph@graph)) == FALSE){ - stop("[NG_graph:graphLayout] random layout nodes not equal to layouted output.\n") - } - - x <- lay[1,] - y <- lay[2,] - - ##rescale graph - graph@xNodes <- (x-min(x))/(diff(range(x))) * - (graph@bbox[1]- 2*graph@border - 2*labelDistR)+graph@border+labelDistR - graph@yNodes <- (y-min(y))/(diff(range(y))) * - (graph@bbox[2]- 2*graph@border - 2*labelDistR)+graph@border+labelDistR - - - # graph@xNodes <- lay[1,]+graph@border - # graph@yNodes <- lay[2,]+graph@border - - graph <- updateLabels(graph, ldist=labelDistR, orientation = 'center') - - - }else if(type == 'kamadaKawaiSpring'){ - - lay <- kamadaKawaiSpringLayout( graph@graph, edge_or_side=1, es_length=1 ) - - if(all(colnames(lay) == nodes(graph@graph)) == FALSE){ - stop("[NG_graph:graphLayout] random layout nodes not equal to layouted output.\n") - } - - x <- lay[1,] - y <- lay[2,] - ##rescale graph - graph@xNodes <- (x-min(x))/(diff(range(x))) * - (graph@bbox[1]- 2*graph@border - 2*labelDistR)+graph@border+labelDistR - graph@yNodes <- (y-min(y))/(diff(range(y))) * - (graph@bbox[2]- 2*graph@border - 2*labelDistR)+graph@border+labelDistR - - graph <- updateLabels(graph, ldist=labelDistR, orientation = 'center') - - - }else if(type == "fruchtermanReingold"){ - - lay <- fruchtermanReingoldForceDirectedLayout(graph@graph) - # gursoyAtunLayout(graph@graph)$gursoyAtunLayout - if(all(colnames(lay) == nodes(graph@graph)) == FALSE){ - stop("[NG_graph:graphLayout] random layout nodes not equal to layouted output.\n") - } - - x <- lay[1,] - y <- lay[2,] - ##rescale graph - graph@xNodes <- (x-min(x))/(diff(range(x))) * - (graph@bbox[1]- 2*graph@border - 2*labelDistR)+graph@border+labelDistR - graph@yNodes <- (y-min(y))/(diff(range(y))) * - (graph@bbox[2]- 2*graph@border - 2*labelDistR)+graph@border+labelDistR - - graph <- updateLabels(graph, ldist=labelDistR, orientation = 'center') - - - - }else{ - stop(paste("[NG_graph:graphLayout] layout type \" ",type, "\" not known")) - } - - - - graph@layout <- type - return(graph) - } -) + f = "graphLayout", + signature = "NG_graph", + definition = function(graph,type,...){ + args <- list(...) + + ## random, kamadaKawaiSpring and fruchtermanReingold kamadaKawaiSpring and fruchtermanReingold currently not + ## working for RBGL 1.32.1 + if(type %in% c("kamadaKawaiSpring", "fruchtermanReingold", "random")) { + message(paste("Note: For graph \"", graph@name, "\" the ", type, " layout is temporarily not supported by the RBGL package, circle layout is used instead", sep ="")) + type <- "circle" + } + + ## ldist stands for label distance (from node) + + ## Distance from the Node Labels to the Node + if(is(args$settings,"NG_Settings")){ + labelDistR <- args$settings@interaction@labelDistRadius + }else if(is.null(args$ldist) == FALSE){ + labelDistR <- args$ldist + }else{ + labelDistR <- 25 + } + + ## circle layout + if(type == 'circle'){ + p <- numNodes(graph@graph) + angle <- seq(0,2*pi, length=p+1)[1:p] + + ## radius of circle for nodes + r <- (min(graph@bbox) - 2*labelDistR - 2*graph@border)/2 + graph@xNodes <- cos(angle)*r + graph@bbox[1]/2 + graph@yNodes <- sin(angle)*r + graph@bbox[2]/2 + + ## radius of circle for label names + + ##graph <- updateLabels(graph, ldist=labelDistR, orientation = 'center') + + r <- (min(graph@bbox) - 2*graph@border)/2 + graph@xLabels <- cos(angle)*r + graph@bbox[1]/2 + graph@yLabels <- sin(angle)*r + graph@bbox[2]/2 + + } + ## Depend on Rgraphviz + ## else if(any(type == c('neato','dot','twopi'))){ + ## + ## ## agopen is from the Rgraphviz library + ## vv <- agopen(graph = graph@graph, name = graph@name, + ## layout = type) + ## + ## x <- sapply(vv@AgNode,function(x)x@center@x) + ## y <- sapply(vv@AgNode,function(x)x@center@y) + ## nodeNames <- sapply(vv@AgNode,function(x)x@txtLabel@labelText) + ## + ## if(any(nodeNames != nodes(graph@graph))){ + ## stop("[NG_graph:grahLayout] order of nodes after Layouting not the same anymore.\n") + ## } + ## + ## + ## ## rescale graph + ## graph@xNodes <- (x-min(x))/(diff(range(x))) * + ## (graph@bbox[1]- 2*graph@border - 2*labelDistR)+graph@border+labelDistR + ## graph@yNodes <- (y-min(y))/(diff(range(y))) * + ## (graph@bbox[2]- 2*graph@border - 2*labelDistR)+graph@border+labelDistR + ## + ## graph <- updateLabels(graph, ldist=labelDistR, orientation = 'center') + ## + ## + ## } + ## else if(type == 'random'){ + ## + ## lay <- randomGraphLayout(graph@graph) + ## + ## if(all(colnames(lay) == nodes(graph@graph)) == FALSE){ + ## stop("[NG_graph:graphLayout] random layout nodes not equal to layouted output.\n") + ## } + ## + ## x <- lay[1,] + ## y <- lay[2,] + ## + ## ##rescale graph + ## graph@xNodes <- (x-min(x))/(diff(range(x))) * + ## (graph@bbox[1]- 2*graph@border - 2*labelDistR)+graph@border+labelDistR + ## graph@yNodes <- (y-min(y))/(diff(range(y))) * + ## (graph@bbox[2]- 2*graph@border - 2*labelDistR)+graph@border+labelDistR + ## + ## ## graph@xNodes <- lay[1,]+graph@border + ## ## graph@yNodes <- lay[2,]+graph@border + ## + ## graph <- updateLabels(graph, ldist=labelDistR, orientation = 'center') + ## + ## } + ## Currently not working for RBGL 1.32.1 + ## else if(type == 'kamadaKawaiSpring'){ + ## + ## lay <- kamadaKawaiSpringLayout( graph@graph, edge_or_side=1, es_length=1 ) + ## + ## if(all(colnames(lay) == nodes(graph@graph)) == FALSE){ + ## stop("[NG_graph:graphLayout] random layout nodes not equal to layouted output.\n") + ## } + ## + ## x <- lay[1,] + ## y <- lay[2,] + ## ##rescale graph + ## graph@xNodes <- (x-min(x))/(diff(range(x))) * + ## (graph@bbox[1]- 2*graph@border - 2*labelDistR)+graph@border+labelDistR + ## graph@yNodes <- (y-min(y))/(diff(range(y))) * + ## (graph@bbox[2]- 2*graph@border - 2*labelDistR)+graph@border+labelDistR + ## + ## graph <- updateLabels(graph, ldist=labelDistR, orientation = 'center') + ## + ## + ## }else if(type == "fruchtermanReingold"){ + ## + ## lay <- fruchtermanReingoldForceDirectedLayout(graph@graph) + ## # gursoyAtunLayout(graph@graph)$gursoyAtunLayout + ## if(all(colnames(lay) == nodes(graph@graph)) == FALSE){ + ## stop("[NG_graph:graphLayout] random layout nodes not equal to layouted output.\n") + ## } + ## + ## x <- lay[1,] + ## y <- lay[2,] + ## ##rescale graph + ## graph@xNodes <- (x-min(x))/(diff(range(x))) * + ## (graph@bbox[1]- 2*graph@border - 2*labelDistR)+graph@border+labelDistR + ## graph@yNodes <- (y-min(y))/(diff(range(y))) * + ## (graph@bbox[2]- 2*graph@border - 2*labelDistR)+graph@border+labelDistR + ## + ## graph <- updateLabels(graph, ldist=labelDistR, orientation = 'center') + ## + ##} + else{ + stop(paste("[NG_graph:graphLayout] layout type \" ",type, "\" not known")) + } + + + + graph@layout <- type + return(graph) + } + ) ## updateLabels updateLabels <- function(graph, ldist, orientation = 'center'){ - if(is(graph,"NG_graph") == FALSE){ - stop("[NG_graph:updateLabels] graph is not from class NG_graph.\n") - } - - if(orientation == 'same'){ - dx <- graph@xLabels - graph@xNodes - dy <- graph@yLabels - graph@yNodes - - dist <- apply(cbind(dx,dy),1,function(row)sqrt(sum(row^2))) - - ratio <- ldist/dist - graph@xLabels <- graph@xNodes + ratio*dx - graph@yLabels <- graph@yNodes + ratio*dy - - - } else if(orientation == 'center'){ - center <- apply(cbind(graph@xNodes,graph@yNodes),2,mean) - - dx <- graph@xNodes-center[1] - dy <- graph@yNodes-center[2] - - dist <- apply(cbind(dx,dy),1,function(row)sqrt(sum(row^2))) - - ratio <- (ldist+dist)/dist - graph@xLabels <- center[1] + ratio*dx - graph@yLabels <- center[2] + ratio*dy - } - - return(graph) + if(is(graph,"NG_graph") == FALSE){ + stop("[NG_graph:updateLabels] graph is not from class NG_graph.\n") + } + + if(orientation == 'same'){ + dx <- graph@xLabels - graph@xNodes + dy <- graph@yLabels - graph@yNodes + + dist <- apply(cbind(dx,dy),1,function(row)sqrt(sum(row^2))) + + ratio <- ldist/dist + graph@xLabels <- graph@xNodes + ratio*dx + graph@yLabels <- graph@yNodes + ratio*dy + + + } else if(orientation == 'center'){ + center <- apply(cbind(graph@xNodes,graph@yNodes),2,mean) + + dx <- graph@xNodes-center[1] + dy <- graph@yNodes-center[2] + + dist <- apply(cbind(dx,dy),1,function(row)sqrt(sum(row^2))) + + ratio <- (ldist+dist)/dist + graph@xLabels <- center[1] + ratio*dx + graph@yLabels <- center[2] + ratio*dy + } + + return(graph) } ## initialize setMethod( - f = "initialize", - signature = "NG_graph", - definition = function(.Object,name,graph,visualization,layout,sep){ - - ## assign values - .Object@name <- name - if(is(graph,"graph")){ - .Object@graph <- graph - }else{ - stop("[NG_graph:initialize] Graph is not from class \"graph\".") - } - .Object@bbox <- c(400,400) - .Object@border <- 40 - - - .Object@layout <- layout - - .Object@sep <- sep - - - ## Make graph Layout - .Object <- graphLayout(.Object, layout) - - validObject(.Object) - return(.Object) - } -) + f = "initialize", + signature = "NG_graph", + definition = function(.Object,name,graph,visualization,layout,sep){ + + ## assign values + .Object@name <- name + if(is(graph,"graph")){ + .Object@graph <- graph + }else{ + stop("[NG_graph:initialize] Graph is not from class \"graph\".") + } + .Object@bbox <- c(400,400) + .Object@border <- 40 + + + .Object@layout <- layout + + .Object@sep <- sep + + + ## Make graph Layout + .Object <- graphLayout(.Object, layout) + + validObject(.Object) + return(.Object) + } + ) ## plot NG_graph setMethod( - f = "plot", - signature = c(x = "NG_graph"), - definition = function(x,y = NULL,...){ - plot(1,1, type = 'n', xlim = c(0,x@bbox[1]), ylim = c(0, x@bbox[2]), - main = paste(x@name,' (\'',x@layout,'\' layout)', sep =''), axes = FALSE, xlab ='', ylab = '') - box() - axis(3,at = c(0,x@bbox[1]), labels = c(0,x@bbox[1]) ) - axis(2,at = c(0,x@bbox[2]), labels = c(x@bbox[2],0) ) - - points(x@xNodes,x@yNodes*-1+x@bbox[2],pch = 19, cex = 2) - text(x@xLabels,x@yLabels*-1+x@bbox[2],nodes(x@graph)) - - - edgeMatrix <- edgeMatrix(as(x@graph,"graphNEL")) - - segments( - x@xNodes[edgeMatrix[1,]], - x@yNodes[edgeMatrix[1,]]*-1+x@bbox[2], - x@xNodes[edgeMatrix[2,]], - x@yNodes[edgeMatrix[2,]]*-1+x@bbox[2]) - - } -) + f = "plot", + signature = c(x = "NG_graph"), + definition = function(x,y = NULL,...){ + plot(1,1, type = 'n', xlim = c(0,x@bbox[1]), ylim = c(0, x@bbox[2]), + main = paste(x@name,' (\'',x@layout,'\' layout)', sep =''), axes = FALSE, xlab ='', ylab = '') + box() + axis(3,at = c(0,x@bbox[1]), labels = c(0,x@bbox[1]) ) + axis(2,at = c(0,x@bbox[2]), labels = c(x@bbox[2],0) ) + + points(x@xNodes,x@yNodes*-1+x@bbox[2],pch = 19, cex = 2) + text(x@xLabels,x@yLabels*-1+x@bbox[2],nodes(x@graph)) + + + edgeMatrix <- edgeMatrix(as(x@graph,"graphNEL")) + + segments( + x@xNodes[edgeMatrix[1,]], + x@yNodes[edgeMatrix[1,]]*-1+x@bbox[2], + x@xNodes[edgeMatrix[2,]], + x@yNodes[edgeMatrix[2,]]*-1+x@bbox[2]) + + } + ) ## constructor function ng_graph <- function(name, graph, sep=':', layout = 'circle'){ - - if (grepl(' ', sep, fixed = TRUE)) { - stop("[ng_graph] sep argument can not contain any spaces.") - } - - if(!any(layout %in% c("circle", "kamadaKawaiSpring", "fruchtermanReingold", "random"))) { - stop('[ng_graph] argument layout must be one of:\n \t "circle", "kamadaKawaiSpring", "fruchtermanReingold", "random"') - } - - num <- sapply(gregexpr(sep, nodes(graph),fixed = TRUE), - FUN = function(x){ - v <- attr(x,'match.length') - if(all(length(v) ==1, v == -1)) { - 0 - } else { - length(v) - } - } - ) - if (!all(num[1] == num)) { - stop(paste("[ng_graph]: warning, the seperator number of occurences of sep in each graph node is\n", - paste(num, collapse = ", "),"\n")) - } - if(num[1] == 0){ - cat("[ng_graph]: warning, sep does not occur in some node names\n") - } - - edgeDataDefaults(graph,"visited") <- FALSE - return(new("NG_graph", name = name, graph = graph, layout = layout, sep = sep)) + + if (grepl(' ', sep, fixed = TRUE)) { + stop("[ng_graph] sep argument can not contain any spaces.") + } + + if(!any(layout %in% c("circle", "kamadaKawaiSpring", "fruchtermanReingold", "random"))) { + stop('[ng_graph] argument layout must be one of:\n \t "circle", "kamadaKawaiSpring", "fruchtermanReingold", "random"') + } + + num <- sapply(gregexpr(sep, nodes(graph),fixed = TRUE), + FUN = function(x){ + v <- attr(x,'match.length') + if(all(length(v) ==1, v == -1)) { + 0 + } else { + length(v) + } + } + ) + if (!all(num[1] == num)) { + stop(paste("[ng_graph]: warning, the seperator number of occurences of sep in each graph node is\n", + paste(num, collapse = ", "),"\n")) + } + if(num[1] == 0){ + cat("[ng_graph]: warning, sep does not occur in some node names\n") + } + + edgeDataDefaults(graph,"visited") <- FALSE + return(new("NG_graph", name = name, graph = graph, layout = layout, sep = sep)) } @@ -317,158 +320,158 @@ ng_graph <- function(name, graph, sep=':', layout = 'circle'){ ## resize the graph setMethod( - f = "resize", - signature = c(object ="NG_graph", width = "numeric", height = "numeric"), - definition = function(object, width, height,...){ - args <- list(...) - - if(is.null(args$ldist)){ - ldist <- 25 - }else if(is(args$ldist,"NG_Settings")){ - ldist <- args$ldist@interaction@labelDistRadius - }else{ - ldist <- args$ldist - } - - ## adjust for border - twoB <- 2*object@border - - object@xNodes <- (object@xNodes-object@border)/ - (object@bbox[1]-twoB)*(width-twoB)+object@border - object@yNodes <- (object@yNodes-object@border)/ - (object@bbox[2]-twoB)*(height-twoB)+object@border - - object@xLabels <- (object@xLabels-object@border)/ - (object@bbox[1]-twoB)*(width-twoB)+object@border - object@yLabels <- (object@yLabels-object@border)/ - (object@bbox[2]-twoB)*(height-twoB)+object@border - - object@bbox <- c(width,height) - - object <- updateLabels(object,ldist,orientation = 'same') - - return(object) - - }) + f = "resize", + signature = c(object ="NG_graph", width = "numeric", height = "numeric"), + definition = function(object, width, height,...){ + args <- list(...) + + if(is.null(args$ldist)){ + ldist <- 25 + }else if(is(args$ldist,"NG_Settings")){ + ldist <- args$ldist@interaction@labelDistRadius + }else{ + ldist <- args$ldist + } + + ## adjust for border + twoB <- 2*object@border + + object@xNodes <- (object@xNodes-object@border)/ + (object@bbox[1]-twoB)*(width-twoB)+object@border + object@yNodes <- (object@yNodes-object@border)/ + (object@bbox[2]-twoB)*(height-twoB)+object@border + + object@xLabels <- (object@xLabels-object@border)/ + (object@bbox[1]-twoB)*(width-twoB)+object@border + object@yLabels <- (object@yLabels-object@border)/ + (object@bbox[2]-twoB)*(height-twoB)+object@border + + object@bbox <- c(width,height) + + object <- updateLabels(object,ldist,orientation = 'same') + + return(object) + + }) setMethod( - f = "adjacent", - signature = "NG_graph", - definition = function(graph,node,type = 'edge', retNr = TRUE){ - - if(any(type == 'edge',type == 'node') == FALSE){ - stop('[ng_graph:adjacent] type argument wrong.\n') - } - - if(length(node)!=1){ - stop('[ng_graph:adjacent] function needs only one node as an argument.\n') - } - - nodeNames <- nodes(graph@graph) - if(is.numeric(node)){ - nodeNr <- node - }else{ - nodeNr <- unlist(match(node,nodeNames)) - } - if(is.na(nodeNr)){ - stop('[ng_graph:adjacent] node not found.\n') - } - if(length(nodeNr)!=1){ - stop('[ng_graph:adjacent] node name not unique.\n') - } - - - adjNodesNames <- unlist(adj(graph@graph,node)) - if(all(type == 'node', retNr == FALSE)){ - return(adjNodesNames) - } - - adjNodesNr <- match(adjNodesNames,nodeNames) - if(all(type == 'node', retNr == TRUE)){ - return(adjNodesNr) - } - - adjEdgesNr <- sapply(adjNodesNr,function(i){which(apply(graph@edgeMatrix,1,function(row){all(range(c(nodeNr,i)) == range(row))}))}) - if(all(type == 'edge', retNr == TRUE)){ - return(adjEdgesNr) - } - - - if(all(type == 'edge', retNr == FALSE)){ - return(edgeNames(graph@graph)[adjEdgesNr]) - }else{ - stop('[ng_graph:adjacent] check arguments.\n') - } - }) + f = "adjacent", + signature = "NG_graph", + definition = function(graph,node,type = 'edge', retNr = TRUE){ + + if(any(type == 'edge',type == 'node') == FALSE){ + stop('[ng_graph:adjacent] type argument wrong.\n') + } + + if(length(node)!=1){ + stop('[ng_graph:adjacent] function needs only one node as an argument.\n') + } + + nodeNames <- nodes(graph@graph) + if(is.numeric(node)){ + nodeNr <- node + }else{ + nodeNr <- unlist(match(node,nodeNames)) + } + if(is.na(nodeNr)){ + stop('[ng_graph:adjacent] node not found.\n') + } + if(length(nodeNr)!=1){ + stop('[ng_graph:adjacent] node name not unique.\n') + } + + + adjNodesNames <- unlist(adj(graph@graph,node)) + if(all(type == 'node', retNr == FALSE)){ + return(adjNodesNames) + } + + adjNodesNr <- match(adjNodesNames,nodeNames) + if(all(type == 'node', retNr == TRUE)){ + return(adjNodesNr) + } + + adjEdgesNr <- sapply(adjNodesNr,function(i){which(apply(graph@edgeMatrix,1,function(row){all(range(c(nodeNr,i)) == range(row))}))}) + if(all(type == 'edge', retNr == TRUE)){ + return(adjEdgesNr) + } + + + if(all(type == 'edge', retNr == FALSE)){ + return(edgeNames(graph@graph)[adjEdgesNr]) + }else{ + stop('[ng_graph:adjacent] check arguments.\n') + } + }) nodeNr <- function(graph,nodes){ - if(length(nodes)>1){ - nodesV <- nodes - }else{ - nodesV <- unlist(strsplit(nodes, " ")) - } - match(nodesV, nodes(graph@graph)) - ## check whether each element is filled + if(length(nodes)>1){ + nodesV <- nodes + }else{ + nodesV <- unlist(strsplit(nodes, " ")) + } + match(nodesV, nodes(graph@graph)) + ## check whether each element is filled } setMethod(f = "ng_get", - signature = "NG_graph", - definition = function(obj, what=NULL, ...){ - possibleOptions <- c("name","graph","visitedEdges","layout") - - if(is.null(what)){ - cat("Get what? Possible options are: ") - cat(paste(possibleOptions, collapse = ", ")) - cat("\n") - }else{ - if(any(is.na(match(what,possibleOptions)))){ - stop(paste("[ng_get] object",what,"is not defined.")) - } - - if(what == "name"){ - return(obj@name) - }else if(what == "graph"){ - return(obj@graph) - }else if(what == "data"){ - return(obj@data) - }else if(what == "layout"){ - return(obj@layout) - } - } - }) + signature = "NG_graph", + definition = function(obj, what=NULL, ...){ + possibleOptions <- c("name","graph","visitedEdges","layout") + + if(is.null(what)){ + cat("Get what? Possible options are: ") + cat(paste(possibleOptions, collapse = ", ")) + cat("\n") + }else{ + if(any(is.na(match(what,possibleOptions)))){ + stop(paste("[ng_get] object",what,"is not defined.")) + } + + if(what == "name"){ + return(obj@name) + }else if(what == "graph"){ + return(obj@graph) + }else if(what == "data"){ + return(obj@data) + }else if(what == "layout"){ + return(obj@layout) + } + } + }) setMethod(f = "ng_set", - signature = "NG_graph", - definition = function(object){ - possibleOptions <- c("name","graph","layout") - paste("Replace what? Possible options are:", paste(possibleOptions, collapse = ", "),'\n') - cat('Use ng_set<- to set a value.\n') - }) + signature = "NG_graph", + definition = function(object){ + possibleOptions <- c("name","graph","layout") + paste("Replace what? Possible options are:", paste(possibleOptions, collapse = ", "),'\n') + cat('Use ng_set<- to set a value.\n') + }) setReplaceMethod( - f = "ng_set","NG_graph", - function(object,what,value){ - possibleOptions <- c("name","graph","layout") - tmp <- object - - if(!(what %in% possibleOptions)) { - stop(paste("Replace what? Possible options are: ", paste(possibleOptions, collapse = ", "),'\n')) - } - - slot(object, what, check = TRUE) <- value - if(validObject(object)){ - return(object) - }else { - cat("[ng_set] assignment is wrong\n") - return(tmp) - } - }) + f = "ng_set","NG_graph", + function(object,what,value){ + possibleOptions <- c("name","graph","layout") + tmp <- object + + if(!(what %in% possibleOptions)) { + stop(paste("Replace what? Possible options are: ", paste(possibleOptions, collapse = ", "),'\n')) + } + + slot(object, what, check = TRUE) <- value + if(validObject(object)){ + return(object) + }else { + cat("[ng_set] assignment is wrong\n") + return(tmp) + } + }) diff --git a/inst/doc/RnavGraph.pdf b/inst/doc/RnavGraph.pdf index 5a0c0a237748468da58ddae38f323c852ee04e67..d6090c1205d6a7d9645d2f3b5a6c4e1b70374fad 100644 GIT binary patch delta 21500 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