diff --git a/NAMESPACE b/NAMESPACE index a0295560..4a73fef2 100755 --- a/NAMESPACE +++ b/NAMESPACE @@ -8,6 +8,7 @@ export("CELL_META") export("add_transparency") export("adjacencyList2Matrix") export("adjacencyMatrix2List") +export("arrange_links_evenly") export("calc_gap") export("chordDiagram") export("chordDiagramFromDataFrame") diff --git a/NEWS b/NEWS index 82c1ec27..3a990811 100755 --- a/NEWS +++ b/NEWS @@ -10,6 +10,7 @@ Changes in version 0.4.12 * `circos.genomicLabels()`: replace `side` argument with `labels.side`. * `circos.points()`, `circos.lines()`, `circos.text()` allow argument `x` to be a two-column matrix. +* add `arrange_links_evenly()` function. Changes in version 0.4.11 ----------------------------------------------------------------------- diff --git a/R/chordDiagram.R b/R/chordDiagram.R index 56e99106..4b180162 100755 --- a/R/chordDiagram.R +++ b/R/chordDiagram.R @@ -754,6 +754,7 @@ chordDiagramFromMatrix = function( # -group It contains the group labels and the sector names are used as the names in the vector. # -big.gap Gaps between the sectors in the first column of ``df`` and sectors in the second column in ``df``. # -small.gap Small gap between sectors. +# -plot Internally used. # -... pass to `circos.link` # # == details @@ -804,6 +805,7 @@ chordDiagramFromDataFrame = function( group = NULL, big.gap = 10, small.gap = 1, + plot = TRUE, ...) { if(!is.null(link.rank)) { @@ -1219,6 +1221,8 @@ chordDiagramFromDataFrame = function( xsum = pmax(x1_sum, x2_sum) } + if(!plot) return(df) + o.cell.padding = circos.par("cell.padding") circos.par(cell.padding = c(0, 0, 0, 0)) o.start.degree = circos.par("start.degree") diff --git a/R/link.R b/R/link.R index d81904fc..9e69d6ea 100755 --- a/R/link.R +++ b/R/link.R @@ -650,3 +650,70 @@ line_degree = function(x0, y0, x1, y1) { if(x0 > x1 && y0 < y1) alpha = (alpha + 180) %% 360 return(alpha) } + + +# == title +# Arrange links evenly on each sector +# +# == param +# -df A data frame with two columns. The values should only contain sector names. +# +# == details +# This function only deals with single-line links. +# +# == value +# A data frame with four columns of the sectors and the positions of the links. +# +# == example +# sectors = letters[1:20] +# df = data.frame(from = sample(sectors, 40, replace = TRUE), +# to = sample(sectors, 40, replace = TRUE)) +# df = unique(df) +# df = df[df$from != df$to, ] +# +# circos.initialize(sectors, xlim = c(0, 1)) +# circos.track(ylim = c(0, 1), panel.fun = function(x, y) { +# circos.text(CELL_META$xcenter, CELL_META$ycenter, CELL_META$sector.index) +# }) +# +# df2 = arrange_links_evenly(df) +# +# for(i in seq_len(nrow(df2))) { +# s1 = df$from[i] +# s2 = df$to[i] +# circos.link(df2[i, "sector1"], df2[i, "pos1"], +# df2[i, "sector2"], df2[i, "pos2"], +# directional = 1) +# } +# +arrange_links_evenly = function(df) { + + if(!is.circos.initialized()) { + stop_wrap("Circular layout needs to be initialized.") + } + + df[, 1] = factor(df[, 1], levels = get.all.sector.index()) + df[, 2] = factor(df[, 2], levels = get.all.sector.index()) + + if(any(is.na(df[, 1])) || any(is.na(df[, 2]))) { + stop_wrap("The two columns in `df` should only contain sector names.") + } + + df2 = chordDiagram(df, plot = FALSE) + + link_count = table(unlist(df)) + + for(i in seq_len(nrow(df2))) { + s1 = df2[i, 1] + s2 = df2[i, 2] + + xlim1 = get.cell.meta.data("xlim", sector.index = s1) + df2[i, "x1"] = (df2[i, "x1"] - 0.5)/(link_count[s1]) * (xlim1[2] - xlim1[1]) + xlim1[1] + xlim2 = get.cell.meta.data("xlim", sector.index = s2) + df2[i, "x2"] = (df2[i, "x2"] - 0.5)/(link_count[s2]) * (xlim2[2] - xlim2[1]) + xlim2[1] + } + df2 = df2[, c("rn", "cn", "x1", "x2")] + colnames(df2) = c("sector1", "sector2", "pos1", "pos2") + return(df2) +} + diff --git a/man/arrange_links_evenly.Rd b/man/arrange_links_evenly.Rd new file mode 100644 index 00000000..8ce8e1fc --- /dev/null +++ b/man/arrange_links_evenly.Rd @@ -0,0 +1,44 @@ +\name{arrange_links_evenly} +\alias{arrange_links_evenly} +\title{ +Arrange links evenly on each sector +} +\description{ +Arrange links evenly on each sector +} +\usage{ +arrange_links_evenly(df) +} +\arguments{ + + \item{df}{A data frame with two columns. The values should only contain sector names. } + +} +\details{ +This function only deals with single-line links. +} +\value{ +A data frame with four columns of the sectors and the positions of the links. +} +\examples{ +sectors = letters[1:20] +df = data.frame(from = sample(sectors, 40, replace = TRUE), + to = sample(sectors, 40, replace = TRUE)) +df = unique(df) +df = df[df$from != df$to, ] + +circos.initialize(sectors, xlim = c(0, 1)) +circos.track(ylim = c(0, 1), panel.fun = function(x, y) { + circos.text(CELL_META$xcenter, CELL_META$ycenter, CELL_META$sector.index) +}) + +df2 = arrange_links_evenly(df) + +for(i in seq_len(nrow(df2))) { + s1 = df$from[i] + s2 = df$to[i] + circos.link(df2[i, "sector1"], df2[i, "pos1"], + df2[i, "sector2"], df2[i, "pos2"], + directional = 1) +} +} diff --git a/man/chordDiagramFromDataFrame.Rd b/man/chordDiagramFromDataFrame.Rd index a9d50064..ddcf891b 100644 --- a/man/chordDiagramFromDataFrame.Rd +++ b/man/chordDiagramFromDataFrame.Rd @@ -46,6 +46,7 @@ chordDiagramFromDataFrame( group = NULL, big.gap = 10, small.gap = 1, + plot = TRUE, ...) } \arguments{ @@ -88,6 +89,7 @@ chordDiagramFromDataFrame( \item{group}{It contains the group labels and the sector names are used as the names in the vector. } \item{big.gap}{Gaps between the sectors in the first column of \code{df} and sectors in the second column in \code{df}. } \item{small.gap}{Small gap between sectors. } + \item{plot}{Internally used. } \item{...}{pass to \code{\link{circos.link}} } } diff --git a/man/get_most_inside_radius.Rd b/man/get_most_inside_radius.Rd index 7ecae7d7..0ded3adc 100644 --- a/man/get_most_inside_radius.Rd +++ b/man/get_most_inside_radius.Rd @@ -12,4 +12,5 @@ get_most_inside_radius() \examples{ # There is no example NULL + }